CH08-结构型-装饰器
模式动机
一般有两种方式可以实现给一个类或对象增加行为:
- 继承机制:通过继承一个类,使子类在拥有自身方法的同时拥有父类的方法。但是这种方式是静态的,用户不能控制增加行为的方式和时机。
- 关联机制:即将一个类的对象嵌入到另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,这个嵌入的被称为装饰器。
装饰器模式以客户透明的方式动态给一个对象附加上更多的责任,客户端并不会觉得对象在装饰前后有什么不同。可以在不创建更多子类的情况下扩展对象的功能。即该模式的动机。
模式定义
装饰器模式(Decorator Pattern),动态给对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比创建子类的实现更为灵活。或称为“包装器”,与适配器别名相同但应用场景不同,或称“油漆工模式”。
模式结构
包含四种角色:
- Component:抽象构件
- ConcreteComponent:具体构件
- Decorator:抽象装饰类
- ConcreteDecorator:具体装饰类
类图
时序图
代码分析
模式分析
- 与继承关系相比,关联关系的主要优势在于不会破坏的类的封装性,而且继承是一种耦合度较大的静态关系,无法在程序运行时动态扩展。在软件开发阶段,关联关系虽然不会比继承关系减少编码量,但是到了维护阶段,由于关联关系具有较好的松耦合性,因此系统会更易维护。而关联关系的缺点则是会比继承关系要多创建更多对象。
- 使用装饰器模式来实现扩展比继承更加灵活,它以对客户透明的方式动态的给一个对象附加更多的责任。该模式可以在不创建更多子类的情况下,扩展对象功能。
实例
变形金刚
变形金刚在变型之前是一辆汽车,它可以在陆地上移动。变型之后除了能够移动外还可以说话;或者变成飞机飞行。
类图:
时序图:
优点
- 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰器比继承更为灵活。
- 可以通过动态的方式来扩展一个对象的功能,通过配置文件在运行时选择不同的装饰器,从而实现不同的行为。
- 通过使用不同的具体装饰类已经这些装饰类的排列组合,可以创造出很多不同行为的组合。或者使用多个不同的具体装饰类装饰同一个对象,得到功能更对强大的对象。
- 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构建类和具体装饰类,在使用时再对其进行组合,原有代码无需改变,符合开闭原则。
缺点
- 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于他们之间的相互连接方式有所不同,而不是他们的类或属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂性,加大学习与理解难度。
- 这种比继承机制更加灵活的特性,同时也意味着装饰模式比继承模式更易出错,排查也更加困难,对于多次装饰的对象,调试时寻找试错可能需要逐级排查,较为繁琐。
适用场景
- 在不影响其它对象的情况下,以动态、透明的方式给单个对象增加职责。
- 需要动态给一个对象增加功能,这些功能也可以动态的被撤销。
- 当不能采用继承的方式对系统中进行扩从或采用继承不利于系统扩展与维护时。有两种情况不适合使用继承:系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类;活类的定义为 final,不能继承。
模式扩展
装饰器模式简化需要注意的问题:
- 一个装饰类的接口必须与被装饰类的接口保持相同,对于客户端来说,对象在被装饰前后都可以一致对待。
- 尽量保持具体构件类 Component 作为一个“轻”类,不要把太多的逻辑和状态放在具体构件类中,可以通过装饰类来完成这些工作
对该模式进行扩展时:如果只有一个具体构件类而没有抽象构件类,那么抽象装饰类可以作为具体构件类的直接子类。
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.