装饰器模式是继承的替代模式,本质上也是通过对象抽象和对象组合的形式完成。装饰器模式也很少用在设计初始阶段,一般在重构或代码扩展阶段。当需要对现有的对象的行为进行增强时使用。
一、装饰器模式
装饰器模式和组合模式放在一起看是有一些相似的,区别在组合模式是对对象的组合且使用阶段是设计阶段,而装饰模式是对对象行为的组合且使用阶段是代码重构或扩展阶段(增强)
二、案例
举个🌰
看过金庸小说的读者都知道,在小说中有一种老江湖都惯用的武器------暗器,暗器顾名思义就是暗中的武器。类似霹雳子、霹雳雷火弹,蔟藜火弹,霹雳毒火弹等等
其中爆炸式暗器都是在霹雳子的基础上演化而来,进一步增大暗器的杀伤力或杀伤范围
咱可以用代码来构思各种霹雳子的演化和组合
首先对霹雳子进行抽象得到爆炸物,可定义该角色为抽象组件
java
public interface BoomThing {
// 获取爆炸物名称
String getName();
// 爆炸物杀伤力强度
int getStrength();
}
霹雳子实现该抽象组件,可定义该角色为具体组件
java
public class PiLiZi implements BoomThing{
@Override
public String getName() {
return "霹雳子";
}
@Override
public int getStrength() {
return 10;
}
}
上述代码为软件设计中的通用设计(多态),那么当前上述代码已经存在的前提下,如何对具体组件(霹雳子)的能力进行增强呢?
一般情况下可使用继承,但是继承会导致子类的泛滥,所以我们选择装饰器模式。
装饰器模式是继承的替代模式,装饰器模式也很少用在设计初始阶段,一般在重构或代码扩展阶段。当需要对现有的对象的行为进行增强时使用
接下来对霹雳子的行为进行增强,先对霹雳子加一个铁片增加杀伤力
定义抽象装饰器,对装饰器(增强物)抽象
java
public abstract class AbstractAddStrengthDecorator implements BoomThing{
protected BoomThing boomThing;
public AbstractAddStrengthDecorator(BoomThing boomThing){
this.boomThing = boomThing;
}
@Override
public String getName() {
return boomThing.getName();
}
@Override
public int getStrength() {
return boomThing.getStrength();
}
}
使用铁片增强威力,该角色可为具体装饰器
java
public class IronSheets extends AbstractAddStrengthDecorator{
public IronSheets(BoomThing boomThing) {
super(boomThing);
}
@Override
public String getName() {
return super.getName() + "加铁片";
}
@Override
public int getStrength() {
return super.getStrength() + 20;
}
}
使用毒气增强威力,该角色可为具体装饰器
java
public class PoisonGas extends AbstractAddStrengthDecorator{
public PoisonGas(BoomThing boomThing) {
super(boomThing);
}
@Override
public String getName() {
return super.getName() + "加毒气";
}
@Override
public int getStrength() {
return super.getStrength() + 100;
}
}
客户端调用
java
public class TestMain {
public static void main(String[] args) {
//单个组合装饰
IronSheets ironSheets = new IronSheets(new PiLiZi());
System.out.println("暗器名称:" + ironSheets.getName() + ",暗器强度:" + ironSheets.getStrength());
//多个组合装饰(解决继承子类泛滥问题)
PoisonGas poisonGas = new PoisonGas(new IronSheets(new PiLiZi()));
System.out.println("暗器名称:" + poisonGas.getName() + ",暗器强度:" + poisonGas.getStrength());
}
}
三、总结
装饰器模式通过嵌套包装多个装饰器对象,可以实现多层次的功能增强。每个具体装饰器类都可以选择性地增加新的功能,同时保持对象接口的一致性