简介
装饰模式(Decorator Pattern):动态的给一个对象增加额外的职责,提供一种比使用子类更加灵活的解决方法。
- 需要在不改变一个对象的基础上增加额外的行为,可以使用关联代替继承,在装饰类中包含原有类和方法,并增加新的方法,从而动态增减对象的职责。
结构和实现
- 角色包括:
- 抽象构件:具体构件和抽象装饰类的父类,声明具体构件的业务方法,使得客户端可以一致的处理装饰前后的类。
- 具体构件:实现抽象构件的业务方法。
- 抽象装饰类:引用抽象构件,并调用具体构件的业务方法。
- 具体装饰类:调用抽象装饰类的方法,并增加新的方法。
- 装饰模式结构。
透明装饰模式
- 是标准的装饰模式,客户端使用抽象构件类引用具体装饰类对象。新增行为需要在原有的业务方法中调用。
- 具体构件和装饰过的构件对客户端透明。
半透明装饰模式
- 使用具体装饰类引用具体装饰类对象。可以单独使用新增的行为,但是不能多次装饰同一个对象,因为新增方法没有在其他具体装饰类中声明。
- 具体构件类型透明,但是具体装饰类型需要制定,不透明。
实例
- 开发图形界面构件库,包括窗体、文本框、列表框等,这些构件需要一些特殊的增强效果,如带滚动条、带黑色边框、既带边框又带滚动条。同时,构件库和增强效果需要经常扩展。
优缺点和适用范围
- 优点:
- 扩展对象功能灵活。使用关联代替继承,灵活且类的个数不会增加过多。
- 可动态扩展功能。通过配置文件和反射运行时选择具体构件和具体装饰类。
- 可多次装饰。通过嵌套构造函数组合装饰类。
- 构件和装饰类独立变化。增加具体构件类和具体装饰类无需修改源码,符合开闭原则。
- 缺点:
- 产生较多的小对象。装饰器对象不能复用,只能处于修饰某个构件的连接上。
- 比继承灵活但是易出错。多次装饰时,排错较为繁琐。
- 适用范围:
- 需要在不影响其他类的情况下,动态透明的给单个对象添加职责。
- 不能采用继承时:系统存在大量扩展,使用继承类的数量过多;类无法继承,如定义为final。
jdk中的应用
- java.io中,InputStream为抽象构件,ObjectInputStream为装饰类。
- ObjectInput可以包装实现InputStream接口的对象。