背景:
让我们从一个咖啡厅开始吧:星巴兹(Starbuzz)是以扩张速度最快而闻名的咖啡连锁店。如果你在街角看到它的店,在对面街角上肯定会看到另一家。
因为扩张速度太快了,他们准备更新下订单系统,以合乎他们饮料供应要求。
进入正题:
他们原先的类设计是这样的:
购买咖啡时,也可以要求加入调料:如蒸奶(Steamed Milk),豆浆(Soy),摩卡(Mocha)等。所以订单系统就成了下面样子的结构:
显然这么多的类是很难维护的,比如牛奶的价格上扬,新增一种调料,就要该很多代码。
另谋出路:为了减少类,我想到了下面方法:在基类中设置需要加的配料的一个布尔值:
下面是加入子类后的继承图:
那么这个设计好吗:
至少发现下面一些问题:
1:调料价钱改变时会使我们改变现有代码。
2:一旦加入新的调料,需要改变超类的cost()方法
等等。。。
下面直接切入装饰者模式吧!
依据这样的思想:我们以饮料为主体,然后在运行时以调料“装饰”饮料。比方说顾客想要摩卡和奶泡深焙咖啡,那么制作过程如下:
1:拿一个深焙咖啡(DarkRoast)对象
2:以摩卡(Mocha)对象装饰它
3:以奶泡(Whip)对象装饰它
4:调用cost()方法,并依赖委托(delegate)将调料的价钱加上去
详细过程如下图:
目前知道的:
装饰者和被装饰者对象有相同的超类型
可以用一个或者多个装饰者包装一个对象
对象可以在任何时候被装饰,所以可以在运行时动态地,不限量地用自己喜欢的装饰者类装饰对象。
下面引入装饰者模式的定义吧:
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
下面让我们把星巴兹饮料也符合此框架吧:
下面就是用此框架的具体实现:
下面是测试代码:
自此装饰者模式介绍完毕。
下面来说说java类库中装饰者模式吧:
我们都知道java.io的类太多了,也许很惊讶,但是知道了装饰者模式,就知道了许多类其实是装饰者。下面是一个典型的对象集合。用装饰者来将功能结合起来,以读取文件数据:
好了,根据上面的介绍我们可以自己自己的Java I/O装饰者了:
扩展FilterInputStream类,并覆盖read()方法就行了
具体细节这里就不介绍了,大家可以参考《Head First设计模式》里面一个把输入流的所有大写字母转成小写的例子。