装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。
假设你的公司要发奖金,一个人有基础奖金,而有的人还有业务增长奖金,个人进步奖金,更高层的人(比如 经理)除了有个人的奖金外,还有团队累计奖金,团队增长奖金 等等。
如果我们使用一个子类来分发这些奖金,那么我们子类的组合会很多很多。
那么我真的要设计这么多类吗?
装饰模式就很好的解决了这一点:
我们可以将简单的发奖金行为放在基础装饰类中, 但将所有其他奖金方法放入装饰中。
客户端代码必须将基础装饰类放入一系列自己所需的装饰中。 因此最后的对象将形成一个栈结构。
实际与客户端进行交互的对象将是最后一个进入栈中的装饰对象(即具体部件)。
1、部件 Component
发放奖金接口
声明封装器和被封装对象的公用接口。
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) 类是被封装对象所属的类。 它定义了基础行为, 但装饰类可以改变这些行为。
(1) 普通职工
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)、经理
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)
基础装饰 (Base Decorator) 类拥有一个指向被封装对象的引用成员变量。 该变量的类型应当被声明为通用部件接口, 这样它就可以引用具体的部件和装饰。 装饰基类会将所有操作委派给被封装的对象(具体部件)。
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) 定义了可动态添加到部件的额外行为。 具体装饰类会重写装饰基类的方法, 并在调用父类方法之前或之后进行额外的行为。
(1)、个人增长工资
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)、个人积累工资
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)、团队增长工资
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)、团队积累工资
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、客户端(Client)
客户端 (Client) 可以使用多层装饰来封装部件, 只要它能使用通用接口与所有对象互动即可。
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();
}
}
运行展示:(普通职工小王)
即 基础装饰类的reward变量 是 SelfIncrease……,而 Seflncrease……的reward变量 是 SelfAccmu……,而SelfAccmu……的reward变量是Staff。
调用方法工资方法时,先调用的是基础装饰类的sentReward方法,而基础装饰类的sentReward方法是 用reward变量 调用sentReward方法,而reward变量又是SelfIncrease……所以 调用SelfIncrease……的sentReward方法,调用SelfIncrease……的sentReward方法,先调用父类的sentReward方法,父类中的reward变量而是 SelfAccmu……,所以调用SelfAccumu……的sentReward方法………………依此类推,其实就是一个递归调用。
debug 自己看看吧