设计模式-装饰者模式
装饰者模式可以动态地给一个对象增加其他职责。就扩展对象功能来说,装饰者模式比生成子类更为灵活。
装饰者模式的应用场景:
- 想透明并且动态地给对象增加新的职责的时候。
- 给对象增加的职责,在未来存在增加或减少可能。
- 用继承扩展功能不太现实的情况下,应该考虑用组合的方式。
装饰者模式的优点:
- 通过组合而非继承的方式,实现了动态扩展对象的功能的能力。
- 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。
- 充分利用了继承和组合的长处和短处,在灵活性和扩展性之间找到完美的平衡点。
- 装饰者和被装饰者之间虽然都是同一类型,但是它们彼此是完全独立并可以各自独立任意改变的。
- 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
装饰者模式的缺点:
- 装饰链不能过长,否则会影响效率。
- 因为所有对象都是Component,所以如果Component内部结构发生改变,则不可避免地影响所有子类(装饰者和被装饰者),也就是说,通过继承建立的关系总是脆弱地,如果基类改变,势必影响对象的内部,而通过组合(Decoator HAS A Component)建立的关系只会影响被装饰对象的外部特征。
- 只在必要的时候使用装饰者模式,否则会提高程序的复杂性,增加系统维护难度。
相关设计原则
- 找到系统中变化的部分,将变化的部分同其它稳定的部分隔开。(在装饰者模式的应用场景里变化的部分是Component的扩展功能。使用Decorator模式可以很好地将装饰者同被装饰者完全隔离开,我们可以任意改变ConcreteComponent或ConcreteDecorator,它们之间不会有任何相互影响。)
- 面向接口编程,而不要面向实现编程。(Component和Decorator都是抽象类实现,其实相当于起到很好的接口隔离作用,在运行时具体操作的也是Component类型的变量引用,这完全是面向接口编程的。)
- 优先使用对象组合,而非类继承。(装饰者模式最成功的地方就是合理地使用了对象组合,通过组合灵活地扩展了Component的功能,所有的扩展的功能都是通过组合而非继承获得的,这从根本上决定了这种实现是高内聚低耦合的。)
- 类应该对扩展开发,对修改关闭。(这是大名鼎鼎的OCP原则,我们在这个系列的第一篇【模式和原则】里就有专门的介绍。在装饰者模式里充分体现了OCP原则,在需要扩展Component的功能的时候,只需要实现一个新的特定的ConcreteDecorator即可,这完全是一种增量开发,不会对原来代码造成任何影响,对用户代码完全是透明的。)
下载:代码