Article directory
1. Definition
The Decorator pattern is a structural design pattern that allows you to bind new behavior to an original object by placing the object in a special wrapper object that contains the behavior.
Second, the problem
Suppose your company wants to issue bonuses, one person has a basic bonus , and some people also have business growth bonuses , personal progress bonuses , and higher-level people (such as managers) have team cumulative bonuses in addition to individual bonuses. Growth bonuses and more.
If we used a subclass to distribute these bonuses, then the combination of our subclasses would be many, many .
So do I really have to design so many classes?
3. Solutions
The Decorator pattern solves this nicely:
we can put the simple bonus action in the base decorator class , but put all the other bonus methods inside the decorator .
Client code must put the base decorator class into a set of decorators it needs. So the final object will form a stack structure.
The object that actually interacts with the client will be the last decorated object ( ie the concrete widget ) to enter the stack.
4. Realization
1. The component Component
issues bonus interface
Declare the public interface of the encapsulator and the encapsulated object.
package com.atmae.decorator;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 13:00
* @Description:
*/
public interface Reward{
/**
* 发放奖金
* @return 奖金
*/
void sendReward();
}
2. Concrete Component
Concrete Component The class is the class to which the encapsulated object belongs. It defines basic behaviors , but decorator classes can change those behaviors.
(1) Ordinary employees
package com.atmae.decorator;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 13:06
* @Description:
*/
public class Staff implements Reward {
String name;
public Staff(String name) {
this.name=name;
}
@Override
public void sendReward() {
System.out.println("普通职工"+this.name+"基础工资:"+5000d);
}
}
(2), manager
package com.atmae.decorator;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 15:22
* @Description:
*/
public class Manage implements Reward{
String name;
public Manage(String name) {
this.name=name;
}
@Override
public void sendReward() {
System.out.println("经理"+this.name+"基础工资为"+10000d);
}
}
3. BaseDecorator
The Base Decorator class has a reference member variable that points to the encapsulated object . The variable's type should be declared as a generic widget interface so that it can refer to specific widgets and decorations. Decorating the base class will delegate all operations to the encapsulated object (concrete widget).
package com.atmae.decorator;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 13:04
* @Description:
*/
public class RewardDecorator implements Reward {
private Reward reward;
public RewardDecorator() {
}
public RewardDecorator(Reward reward) {
this.reward = reward;
}
@Override
public void sendReward() {
reward.sendReward();
}
}
4. Concrete Decorators
Concrete Decorators defines additional behaviors that can be dynamically added to components. The concrete decorated class overrides the method of the decorated base class and performs additional behavior before or after the parent class method is called.
(1), personal increase salary
package com.atmae.decorator;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 13:58
* @Description:
*/
public class SelfAccumulationRewardDecorator extends RewardDecorator{
public SelfAccumulationRewardDecorator(Reward reward) {
super(reward);
}
public SelfAccumulationRewardDecorator() {
}
@Override
public void sendReward() {
super.sendReward();
System.out.println("\t\t个人累计工资:"+3000d);
}
}
(2) Personal accumulated wages
package com.atmae.decorator;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 13:56
* @Description:
*/
public class SelfIncreaseRewardDecorator extends RewardDecorator{
public SelfIncreaseRewardDecorator(Reward reward) {
super(reward);
}
public SelfIncreaseRewardDecorator() {
}
@Override
public void sendReward() {
super.sendReward();
System.out.println("\t\t个人增长工资:"+2000d);
}
}
(3), the team increases the salary
package com.atmae.decorator;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 15:37
* @Description:
*/
public class TeamIncreaseRewardDecorator extends RewardDecorator{
public TeamIncreaseRewardDecorator() {
}
public TeamIncreaseRewardDecorator(Reward reward) {
super(reward);
}
@Override
public void sendReward() {
super.sendReward();
System.out.println("\t\t团队增长工资:"+4000d);
}
}
(4), the team accumulates wages
package com.atmae.decorator;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 13:57
* @Description:
*/
public class TeamAccumulationRewardDecorator extends RewardDecorator{
public TeamAccumulationRewardDecorator(Reward reward) {
super(reward);
}
public TeamAccumulationRewardDecorator() {
}
@Override
public void sendReward() {
super.sendReward();
System.out.println("\t\t团队积累工资:"+6000d);
}
}
5, the client (Client)
The client (Client) can use multiple layers of decoration to encapsulate components, as long as it can use a common interface to interact with all objects.
package com.atmae.decorator;
import java.awt.*;
/**
* @Author: Mae
* @Date: 2022/4/2
* @Time: 14:39
* @Description:
*/
public class Client {
public static void main(String[] args) {
RewardDecorator rewardDecorator=new SelfIncreaseRewardDecorator(new SelfAccumulationRewardDecorator(new Staff("小王")));
rewardDecorator.sendReward();
RewardDecorator rewardDecorator1=new TeamAccumulationRewardDecorator(new SelfAccumulationRewardDecorator(new Manage("老刘")));
rewardDecorator1.sendReward();
}
}
Running display: (Ordinary employee Xiao Wang)
That is, the reward variable of the basic decoration class is SelfIncrease..., and the reward variable of Seflncrease... is SelfAccmu..., and the reward variable of SelfAccmu... is Staff.
When calling the method salary method, the sentReward method of the basic decoration class is called first, and the sentReward method of the basic decoration class is to use the reward variable to call the sentReward method, and the reward variable is SelfIncrease... So call the sentReward method of SelfIncrease... and call The sentReward method of SelfIncrease... first calls the sentReward method of the parent class, and the reward variable in the parent class is SelfAccmu..., so calling the sentReward method of SelfAccumu... ...... And so on, it is actually a recursive call .
debug and see for yourself
Five, UML diagram
6. Application scenarios of decoration mode
- To use an object without modifying the code, and want to add additional behavior to the object at runtime, you can use the decorator pattern
- Inheritance to extend the behavior of an object is difficult or impossible to achieve, you can use this pattern.
7. Summary
advantage
- You can extend the behavior of an object without creating new subclasses.
- You can add or remove the functionality of an object at runtime.
- You can combine several behaviors by wrapping objects with multiple decorations.
- Single Responsibility Principle. You can split a large class that implements many different behaviors into several smaller classes.
shortcoming
- It is difficult to remove a specific wrapper from the wrapper stack.
- It is difficult to implement decorations whose behavior is not affected by the order of the decoration stack.
- Initial configuration code for layers may look bad
8. Relationship with other modes
- The Decorative Pattern and Strategy Pattern allow you to change the appearance of an object, and the Strategy pattern allows you to change its essence. Decorative pattern is recursive call, strategy pattern is one call.