[Design Patterns] Structural Patterns - Decorative Patterns

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 .
insert image description here

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();
    }
}

insert image description here
Running display: (Ordinary employee Xiao Wang)
insert image description here
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
insert image description here

Five, UML diagram

insert image description here

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.

Guess you like

Origin blog.csdn.net/weixin_51799151/article/details/123913250