开放—关闭原则:类应该对扩展开放,对修改关闭。
对扩展开放:欢迎用任何你想要的行为来扩展我们的类。如果你的需要或需求有所改变,那就来吧!动手扩展吧!
对修改关闭:我们花了许多时间得到了正确的代码,还解决了所有的bug,所以不能让你修改现有代码。我们必须关闭代码以防止被修改。
简单说就是,在不修改代码的情况下,进行功能扩展。在上一章学到的观察者模式即遵循了这个原则:通过加入新的观察者,我们可以再任何时候扩展Subject,而且不需要向主题中添加代码。
星巴兹遇到的问题:类数量爆炸、基类加入的新功能并不适用于所有子类。
以装饰者模式的思路来解决这些问题:我们要以饮料为主体,然后在运行时以调料来“装饰”(decorate)饮料。
比方说,如果顾客想要摩卡和奶泡深焙咖啡,那么,要做的是:
- 拿一个深焙咖啡(DarkRoast)对象
- 以摩卡(Mocha)对象装饰它
- 以奶泡(Whip)对象装饰它
- 调用cost()方法,并依赖委托(delegate)将调料的价钱加上去。
装饰者模式一般类图:
星巴兹案例类图:
缺点:
- 利用装饰者模式,常造成设计中有大量的小类,数量多,可能会造成使用此API程序员的困扰。但了解装饰者模式后,可以较容易地辨别出他们的装饰者类是如何组织的,以方便用包装方式取得想要的行为。
- 如果人们在客户代码中依赖某种特殊类型,然后忽然导入装饰者,又没有周详地考虑一切,就会出现问题。插入装饰者时,必须要小心谨慎。(没懂)
- 采用装饰者在实例化组件时,将增加代码复杂度。一旦使用装饰者模式,不只需要实例化组件,还要把此组件包装进装饰者中,如果该组件要需要一大堆的装饰者来包装,那实例化的那句代码会有超长的一行,比如下图:
工厂(Factory)模式和生成器(Builder)模式会对第3个问题有很大帮助。