文中列举了两个例子,一个是在咖啡厅点饮料,另一个是在java i/o stream中的应用。下面利用第一个例子详细的分析一下装饰者模式。咖啡会分为多种咖啡,顾客在点咖啡时,可能会在点这一杯咖啡的基础上添加一种或多种调味品,如加牛奶、糖、摩卡、豆浆等等。这里顾客点的咖啡就是被装饰者,而调味品则扮演装饰者的角色。
这个模式的显著特征是可以做到多个类的叠加,递归嵌套对象。要做到这点,首先各种具体被装饰者和抽象装饰者要都继承于同一个基类,且装饰者拥有一个指向基类的指针。结合例子,各种咖啡和调味品的抽象是饮料,抽象调味品中拥有一个饮料对象,当需要多种调味品时,就在原有饮料的基础上添加,将加了调味品的具体咖啡赋值给新的调味品中的饮料对象。在计算总价时,先从外到内,最外层的装饰者的cost()会调用内层的cost(),直到最内层也就是被装饰者的cost(),再从内向外计算,得到最终的总价。
装饰者模式体现了面向对象设计中的
开闭原则,对扩展开放,对修改封闭。无论是被装饰者和装饰者的设计上都便于它们的具体类别的扩展,并且不影响已有的具体类。这个模式也有他的缺点,(1)设计中可能会引入大量小类,(2)类型问题,当代码依赖于特定类型时,会有插入装饰者问题。(3)实例化组件时会增加代码复杂度,这个可以结合工厂模式和生成器模式改善。
重点代码:
void CoffeeA::cost()
{
return 1.2;
}
void concreteDecoratorA::concreteDecoratorA(Beverage *beverage)
{
this->m_pBeverage = beverage;
}
void concreteDecoratorA::cost()
{
return beverage.cost()+1.3;
}
void concreteDecoratorB::concreteDecoratorB(Beverage *beverage)
{
this->m_pBeverage = beverage;
}
void concreteDecoratorB::cost()
{
return beverage.cost()+1.3;
}
client:
Beverage *pBeverage = new CoffeeA();
concreteDecoratorA *pConDecA = new concreteDecoratorA(pBerverage);
concreteDecoratorB *pConDecB = new concreteDecoratorB(pConDecA);
pConDecB->cost();