装饰模式
定义
装饰模式(Decorator Pattern
):动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。
场景
现有一个加密模块,可以对字符串明文加密,有不同的加密方法,不同场景下对加密的级别不同,可能在有些业务场景需要用不同的加密方法多次加密,要求能够以任意组合方式加密。难道我们直接把所有加密方式来一个排列组合吗?假设有3种加密方式,岂不是要有15种加密组合?这时候可以使用装饰模式。
UML类图
代码
decorator
示例:
public class TestDecorator {
@Test
public void test() {
Encryption encryptionDefault = new EncryptionDefault();
System.out.println(encryptionDefault.encode("123"));//ONM
AesDecorator aesDecorator = new AesDecorator(encryptionDefault);
System.out.println(aesDecorator.encode("123"));//kc+R5gyXM4NJ/pe7PtWWEw==
System.out.println(aesDecorator.decode("kc+R5gyXM4NJ/pe7PtWWEw=="));//123
Base64Decorator base64Decorator = new Base64Decorator(encryptionDefault);
System.out.println(base64Decorator.encode("123"));//T05N
System.out.println(base64Decorator.decode("T05N"));//123
DesDecorator desDecorator = new DesDecorator(encryptionDefault);
System.out.println(desDecorator.encode("123"));//1D059D1AE2A2C6E1
System.out.println(desDecorator.decode("1D059D1AE2A2C6E1"));//123
DesDecorator desDecorator1 = new DesDecorator(new AesDecorator(new Base64Decorator(encryptionDefault)));
System.out.println(desDecorator1.encode("123"));//BEED6F244E2241FC23402F604BF6DB4F93BB55C75500C11F50A40173C455AEF1
System.out.println(desDecorator1.decode("BEED6F244E2241FC23402F604BF6DB4F93BB55C75500C11F50A40173C455AEF1"));//123
}
}
总结
装饰模式降低了系统的耦合度,可以动态增加或删除对象的职责,并使得需要装饰的具体构件类和具体装饰类可以独立变化,以便增加新的具体构件类和具体装饰类。在软件开发中,装饰模式应用较为广泛,例如在JavaIO中的输入流和输出流的设计、javax.swing包中一些图形界面构件功能的增强等地方都运用了装饰模式。
它跟桥接模式的区别有二:
- 桥接模式抽象和实现是两个类型,抽象对实现是引用关系,所以不能由抽象和实现完成“多次桥接”,但装饰模式装饰器和具体实现类都继承或实现了抽象,完全可以实现多个装饰器装饰同一个对象,因为装饰器也是具体实现;
- 桥接实现两个维度的单独扩展和自由组合,装饰实现单个维度的扩展和自由组合。
装饰模式在让编写所有组合的类变成了自由装饰基本类,大大减少了累的数量,简化了系统并且组装功能非常灵活,如果需要添加新的基本类和装饰类都不需要修改原有的代码,遵循开闭原则。
当一个基本类套上了多个装饰类的时候,一旦出错,可能导致很难排查,增加了调试和维护成本。所以综上,装饰模式适用于增强特定类的现有功能,或者给现有类增加职责而不去改变现有类的代码,特别是增强那些不可变类final class
,或者通过继承增加类的职责会导致系统类个数爆炸增长的情况。