12.结构型 - 装饰模式 (Decorator Pattern)
装饰模式 (Decorator Pattern)
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能, 同时又不改变其结构; 大多数情况下继承是属于高度耦合的关系, 能使用则多使用该模式替代需要多重继承
装饰类和被装饰类可以独立发展, 不会相互耦合, 装饰模式是继承的一个替代模式, 装饰模式可以动态扩展一个实现类的功能;
比如, JDK中的处理IO流中的FilterInputStream BufferedInputStream 均对 InputStream 做了包装
java.io.InputStream
java.io.FilterInputStream
java.io.BufferedInputStream
装饰类和被装饰类可以独立发展, 不会相互耦合, 装饰模式是继承的一个替代模式, 装饰模式可以动态扩展一个实现类的功能;
意图: 动态地给一个对象添加一些额外的职责; 就增加功能来说, 装饰器模式相比生成子类更为灵活;
主要解决: 一般的, 我们为了扩展一个类经常使用继承方式实现, 由于继承为类引入静态特征, 并且随着扩展功能的增多, 子类会很膨胀;
代码实例
例: 一个毛坯房装修的例子
1.定义一个房子的展示行为 (抽象主体)
public interface Showable {
public void show();//定义展示行为
}
2.最原始的毛坯房啥也没有 (原始实现)
public class House extends Showable {
public void show(){
System.out.print("毛坯房")
}
}
3.开始装修: 先粉刷一遍 (装饰1)
public class PinkHouse extends Showable {
public Decorator(Showable showable) {//待粉刷的 House
this.showable = showable;
}
public void show(){
System.out.print("粉色的(")
showable.show();
System.out.print(")");//粉刷完工
}
}
4.再装一点灯饰 (装饰2)
public class LightHouse extends Showable {
public Decorator(Showable showable) {//待装饰的 House
this.showable = showable;
}
public void show(){
System.out.print("十分明亮的(")
showable.show();
System.out.print(")");//装饰完工
}
}
5.测试
public static void main(String[] args) {
Showable hose = new LightHouse(//十分明亮的
new PinkHouse(//粉色的
new House()//毛坯房
)
);
hose.show();
}
in short 像包装一样, 每增加一个功能, 多一层包装, 使得即添加新功能, 同时又不改变其结构
装饰器模式总结
关键角色
- 抽象主体
- 具体主体(被装饰者)
- 装饰者角色(多个, 扩展 被装饰者的功能)
装饰器模式的优缺点
装饰器模式的优点:
- 对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加 ,
- 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为.
- 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合可以创造出很多不同行为的组合,得到更加强大的对象.
- 具体构建类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构建类和具体装饰类,原有类库代码无需改变,符合开闭原则.
in short 比继承灵活; 可动态的, 多次的组合; 各个类之间独立
装饰器模式的缺点:
- 在使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值不同,大量的小对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能.
- 装饰器模式提供了一种比继承更加灵活、机动的解决方案,但同时也意味着比继承更加易于出错,排错也更加困难,对于多次装饰的对象,在调试寻找错误时可能需要逐级排查,较为烦琐.
in short 容易产生很多的小对象; 调试困难
装饰器模式的适用场景
- 快速动态扩展和撤销一个类的功能场景。 比如,有的场景下对 API 接口的安全性要求较高,那么就可以使用装饰模式对传输的字符串数据进行压缩或加密。如果安全性要求不高,则可以不使用。
- 不支持继承扩展类的场景。 比如,使用 final 关键字的类,或者系统中存在大量通过继承产生的子类。
预防老年痴呆,保持终身学习! —— daidaidaiyu

浙公网安备 33010602011771号