设计原则:类应该对扩展开放,对修改关闭。
注意是类的扩展-修改,而不是业务流程代码,当有新的行为时,业务流程代码肯定要变,但是类可以不变和复用。
继承没有弹性,那是因为类的行为在编译时就静态决定了,想改变行为,必须修改源代码。组合有弹性,是因为类的行为是通过组合的超类调用的,当超类引用指向不同的实现类对象时,只用扩展实现类对象而不用修改类的源代码,类就能产生不同的行为,这种就可以说类的行为在运行时动态决定,这增加了该类的弹性和复用性。
只要将变化的部分抽离,和不变的部分隔离开来,就会很好的实现扩展-修改原则,扩展的时候,最好不要用继承,而要用组合+多态进行扩展,这样可以动态的添加新的行为。
设计中不是每一个部分都应用开放-关闭原则的,这样实在是一种浪费,且导致代码变得复杂且难以理解。你需要把注意力集中在设计中最有可能改变的地方,然后应用开放-关闭原则。
装饰者模式:动态的将责任附加到对象上。
装饰者模式完全符合该扩展-修改原则。
装饰者和被装饰者拥有相同的超类型。装饰者组合被装饰者,委托其产生行为,并在该行为前/后加上自己的包装行为。
装饰的层数过多,有可能导致代码的疏漏,因此一般结合工厂模式或生成器使用。如果不了解装饰者模式,当面对大量的装饰者和被装饰者时,会造成极大的困扰。
总结
装饰,必须有一个基础组件作为被装饰者。比如一杯咖啡是基础组件,那么拿铁咖啡,卡布奇诺咖啡,冰咖啡,大杯咖啡就是装饰者,装饰者在装饰基础组件后,就变成了被装饰者,被装饰者外面又可以被装饰者嵌套。由于大家都是咖啡,而类中都是用咖啡这个超类进行调用,所以包装的顺序可以随意组合的。大杯(冰(拿铁(咖啡))),这种包装关系,最后的大杯咖啡仍是咖啡,调用方是无感知的,但是其功能却增强了。
抽离变化的部分:不变的是基础组件,变化的部分是在组件的基础上会添加各种各样变化的包装。