一、概述
装饰模式是一种对象结构型模式,它是一种用于替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。在装饰模式中引入了装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩充原有类的功能。
装饰模式结构图如下图所示:
二、代码设计
装饰模式的核心在于抽象装饰类Decorator的设计,典型代码如下:
1 | public class Decorator implements Component { |
Decorator的子类为具体装饰类,将继承operation操作,并根据需要扩展operation,典型的具体装饰类代码设计如下:
1 | public class ConcreteDecorator extends Decorator { |
三、透明装饰模式与半透明装饰模式
注意到抽象装饰类Decorator的operation方法,当具体的装饰类ConcreteDecorator所添加的新方法addedOperation与原有的operation方法彼此独立,没有任何调用关系时,此时的装饰模式为半透明装饰模式,此时具体的ConcreteDecorator装饰类中不需要继承operation方法,而是直接添加addedOperation。即:
1 | public class ConcreteDecorator extends Decorator { |
在调用时,半透明装饰模式调用为:
1 | Component c; |
而透明装饰模式的调用为:
1 | Component c,cd; |
另外,如果只有一个ConcretComponent类,那么抽象Decorator类可以作为改ConcretComponent类的直接子类,其unl图如下图所示:
四、demo
设计一个加密算法,首先对原始密码进行简单加密,接着对简单加密过后的密码进行额外的复杂加密工作。
component接口如下:
1 | public interface Cipher { |
ConcreteComponent类实现该接口:
1 | public class SimpleCipher implements Cipher{ |
抽象的Decorator类继承Component:
1 | public class CipherDecorator implements Cipher{ |
ConcreteDecrator类继承抽象的Decorator,并添加额外的加密方法:
1 | public class ComplexCipher extends CipherDecorator { |
1 | public class AdvancedCipher extends CipherDecorator{ |
具体的调用如下:
1 | public static void main(String args[]) { |
运行结果:
五、总结
1. 优点
- 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。
- 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为。
- 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。
- 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则”。
2. 缺点
- 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用更多的系统资源,在一定程序上影响程序的性能。
- 装饰模式提供了一种比继承更加灵活机动的解决方案,但同时也意味着比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。
3. 适用场景
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式。