装饰者模式(Decorator):动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案。
结构图:
- 抽象构件类(Component):给出一个抽象的接口,用以规范准备接收附加责任的对象
- 具体构件类(ConcreteComponent):定义一个具体的准备接受附加责任的类,其必须实现Component接口。
- 装饰者类(Decorator):持有一个构件(Conponent)对象的实例,并定义一个和抽象构件一致的接口。
- 具体装饰者类(Concrete Decoratator):定义给构件对象“贴上”附加责任。
下面用一个实例来讲解一下装饰者模式《head first 设计模式》中的例子:比如在星巴兹咖啡馆,人们需要根据自己的爱好来订购咖啡,而具体的coffee种类假设一共用两类:HouseBlend(混合咖啡)和darkRoast(深焙咖啡)。而另外客人也可根据的口味来添加一些其他的东西,例如:摩卡(mocha)、Milk(牛奶)。
从实例中可以分析出:抽象构件类对应的就是coffee饮品(下面的beverage类),具体构件类对应的就是HouseBlend和darkRoast;具体装饰者类对应mocha和milk口味;至于装饰者类这里没有对应,主要用于具体装饰者类的继承。下面看具体d
源代码:
抽象构件类(Component):
Beverage.java:
/** * @author haifei * 抽象构件类 */ public abstract class Beverage { String description = "未知的咖啡"; public String getDescription(){ return description; } public abstract double cost(); }
具体构件类(ConcreteComponent):
DarkRoast.java:
/** * @author haifei * 具体构件类 */ public class DarkRoast extends Beverage{ public DarkRoast(){ description = "深焙咖啡"; } @Override public double cost() { return 1.0; } }
HouseBlend.java:
/** * @author haifei * 具体构件类。HouseBlend代表咖啡中的一种:混合咖啡 */ public class HouseBlend extends Beverage{ public HouseBlend() { description = "混合咖啡"; } @Override public double cost() { return .89; } }
装饰者类(Descorator):
ConimentDecorator.java:
/** * @author haifei * 抽象装饰者类,所有的具体装饰者都必须继承这个类 */ public abstract class CondimentDecorator extends Beverage{ public abstract String getDescription(); }
具体装饰者类(ConcreteDescorator):
Mocha.java:
public class Mocha extends CondimentDecorator{ Beverage beverage; public Mocha(Beverage beverage){ this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + ",摩卡"; } @Override public double cost() { return beverage.cost() + .20; } }
Milk.java:
public class Milk extends CondimentDecorator{ Beverage beverage; public Milk(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + " ,牛奶"; } @Override public double cost() { return beverage.cost() + .10; } }
客户端(Client):
StarBuzzCoffee.java:
public class StarBuzzCoffee { public static void main(String[] args){ Beverage beverage1 = new DarkRoast(); beverage1 = new Milk(beverage1); beverage1 = new Mocha(beverage1); System.out.println(beverage1.getDescription() + "$" + beverage1.cost()); Beverage beverage2 = new HouseBlend(); beverage2 = new Milk(beverage2); beverage2 = new Mocha(beverage2); System.out.println(beverage2.getDescription() + "$" + beverage2.cost()); } }
运行结果:
深焙咖啡 ,牛奶,摩卡$1.3 混合咖啡 ,牛奶,摩卡$1.19