标签:
现在有一家咖啡厅,里面有四种不同的咖啡种类,而每种不同的咖啡都可以附加牛奶、豆浆、奶泡或者摩卡,而且每次客人点餐,还可以附加多倍的某种配料,比如双倍摩卡。如果使用简单的类继承方法,就要写数量庞大的类,而且很难管理类似于“双倍摩卡”这种形式。
于是,我们就可以引入装饰模式,装饰模式动态地将责任附加到对象上,扩展功能时,提供了比继承更有弹性的替代方案,
装饰模式的类图如下:
装饰模式的特点是
1.装饰者必须能取代被装饰者,也就是说装饰者和被装饰者要用共同的父类。上图的ConcreteComponent类就是被装饰者,ConcreteDecoratorA和B就是装饰者
2.装饰者中含有一个其父类的引用,用来表明被装饰者或者其他装饰者。在装饰者的方法中,往往要先调用这个引用的同名方法。
比如,现在我要一杯摩卡奶泡深度烘焙咖啡,计算价格的过程应该是这样的。
Whip中保存的是Mocha的引用,Mocha中保存的是DarkRoast(被装饰者)的引用,通过循环调用,最后就计算出了价格。
一开始我的疑问是,为什么装饰者必须能取代被装饰者,如果被装饰者和装饰者的父类不一样,会怎么样呢?
思考了以下以后发现,如果被装饰者和装饰者的父类不一样,这意味着装饰者内部必须还要保存一个被装饰者的引用,而假如需要双重和多重的装饰者,则多个装饰者无法联系在一起,被装饰者也不知道其装饰者的存在。
代码参考如下:
Beverage类
/**
饮料类,是装饰者和被装饰者都继承的类。
**/
public abstract class Beverage
{
String description="unknown";
public String getDescription()
{
return description;
}
public abstract double cost();
}
CondimentDecorator类
/**
装饰者类,所有装饰者都继承自这个类
**/
public abstract class CondimentDecorator extends Beverage
{
public abstract String getDescription();
}
DarkRoast类
/**
被装饰者类,表示其中一种咖啡(深度烘焙)
**/
public class DarkRoast extends Beverage
{
public DarkRoast()
{
this.description="DarkRoast";
}
public double cost()
{
return 0.99;
}
}
还有其他的被装饰者类,Decas,Espresso, HouseBlend的代码省略
Milk类
/**
装饰者,继承了CondimentDecorator,表示其中一个装饰者
**/
public class Milk extends CondimentDecorator
{
Beverage beverage;//用一个实例变量记录被装饰者
public Milk(Beverage beverage)//通过构造方法把被装饰者的引用传递过来
{
this.beverage=beverage;
}
public String getDescription()
{
return beverage.getDescription()+",Milk";
}
public double cost()//先计算被装饰对象的价钱,再加上该装饰品的价钱。
{
return 0.10+beverage.cost();
}
}
其他的装饰者类,Mocha,Soy,Whip的代码省略
测试类
package com.qingfei.decorator;
public class Test
{
public static void main(String[] args)
{
Beverage beverage=new Espresso();
System.out.println(beverage.getDescription()+"$"+beverage.cost());
Beverage beverage2=new DarkRoast();
beverage2=new Mocha(beverage2);
beverage2=new Whip(beverage2);
beverage2=new Soy(beverage2);
System.out.println(beverage2.getDescription()+"$"+beverage2.cost());
}
}
输出结果是
这样一来,就可以动态地为被装饰者添加装饰者了,当要扩展的时候,只需要增加一个装饰者的类即可,而装饰者类的修改对于被装饰者类没有影响,符合了开闭原则。
标签:
原文地址:http://www.cnblogs.com/qingfei1994/p/4238445.html