在装饰者模式一章中,Head Fist一书主要是通过“星巴兹咖啡馆”的例子,来讲解优化代码,并将装饰者模式自然而然的融入进去。
本例粗略介绍:有一家名叫“星巴兹”的咖啡连锁店,因扩张速度过快,要更新订单系统,以合乎饮料供应的要求。然而,他们原来的类设计全部是基于Beverage超类,通过子类的继承得来的,由于饮料有很多的种类,调料又有很多的种类,而星巴兹会根据所加入的调料收取不同的费用,因此当做订单系统的时候通过饮料喝各种调料的各种组合就会出来很多的子类。而且当某项调料或者饮料价格做调整的时候会造成很多子类都要跟着改变。问如何妥善的解决这些问题。
本例主要要解决的问题:类数量爆炸、设计死板,以及基类加入的新功能并不适用于所有的子类。
本章中出现的设计原则:类应该对扩展开放,对修改关闭。(俗称开放-关闭原则)
设计原则详解:我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可以搭配新的行为。如能实现这样的目标,有什么好处呢?这样的设计具有弹性可以应对改变,可以接受新的功能来应对改变的需求(摘自HeadFist page86)。
装饰者模式定义:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者模式的适用条件:为某个功能动态的去附加责任,需要针对原来功能的实现方法做另一种实现。限定为同一种方法。(解释的较模糊不准确,需以后再次修改)
装饰者模式的实现:装饰者与被装饰者需要继承(实现)同一个抽象类(接口),装饰者需根据业务需求再建一个抽象类去继承父类以便重新定义某些方法供子类去实现。通过继承(实现)去完成具体的被继承者及继承者类。然后需通过多态达到“类型匹配”,通过装饰者对被装饰者一层层的装饰达到需求的目的(感觉和洋葱的结构差不多。。。)
疑难问答:
问:CondimentDecorator扩展自Beverage类,这用到了继承,不是吗?
答:是的,但是重点在于,装饰者和被装饰者必须是一样的类型,也就是有共同的超类,这是相当关键的地方。在这里,我们利用继承达到“类型匹配”,而不是利用继承获得“行为”。
组合相比于继承的优势:利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
由于在用装饰者模式实现功能时会加入大量的小类,这会导致别人在不知道此模式的情况下去读懂这些代码,理清这些代码之间的关系。