1. 装饰者模式UML类图
2. 装饰者模式要点
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
结合类图,总结装饰者模式要点如下:
a. 组合和委托可用于在运行时动态地加上新的行为。
b. 装饰者模式意味着一群装饰者类,这些类用来包装具体组件。
c. 装饰者类反映出被装饰的组件类型(事实上,他们具有相同的类型,都经过接口或继承实现)。
d. 装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得更复杂。
3. 装饰者模式实现
参照类图,以Coffee(咖啡)为组件(Component),Mocha(摩卡)、Soy(豆浆)、Milk(牛奶)为装饰者(Decorator)实现装饰者模式。
/**
* 咖啡类(超类)
*/
public abstract class Coffee {
/** 咖啡信息描述 */
protected String desc = "Unknown Beverage";
public String getDescription() {
return desc;
}
/** 花费 */
public abstract double cost();
}
/**
* 调料抽象类,也是是装饰者类(装饰咖啡)
*/
public abstract class CondimentDecorator extends Coffee {
/** 被装饰者 */
protected Coffee coffee;
public CondimentDecorator(Coffee cof) {
coffee = cof;
}
/**
* 所有子类都需要重新实现getDescription()方法
*/
public abstract String getDescription();
}
/**
* Espresso,咖啡的一种
*/
public class Espresso extends Coffee {
public Espresso() {
this.desc = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
/**
* HouseBlend,咖啡的一种
*/
public class HouseBlend extends Coffee {
public HouseBlend() {
this.desc = "HouseBlend";
}
@Override
public double cost() {
return 0.89;
}
}
/**
* Mocha,摩卡,是咖啡调料的一种。
*/
public class Mocha extends CondimentDecorator {
public Mocha(Coffee cof) {
super(cof);
}
@Override
public String getDescription() {
return coffee.getDescription() + ", Mocha";
}
@Override
public double cost() {
return coffee.cost() + 0.2;
}
}
/**
* Soy,豆浆,可用作咖啡调料。
*/
public class Soy extends CondimentDecorator {
public Soy(Coffee cof) {
super(cof);
}
@Override
public String getDescription() {
return coffee.getDescription() + ", Soy";
}
@Override
public double cost() {
return coffee.cost() + 0.15;
}
}
/**
* Milk,牛奶,可用作咖啡调料。
*/
public class Milk extends CondimentDecorator {
public Milk(Coffee cof) {
super(cof);
}
@Override
public String getDescription() {
return coffee.getDescription() + ", Milk";
}
@Override
public double cost() {
return coffee.cost() + 0.25;
}
}
/**
* 测试类
*/
public class DecoratorTester {
/**
* 测试方法
*/
public void test() {
/** 客户只点了一杯Espresso咖啡 */
Coffee coffee = new Espresso();
System.out.println(coffee.getDescription() + " $" + coffee.cost());
/** 客户点了一杯HouseBlend咖啡,外加一份Mocha调料、一份Soy调料、一份Milk调料。 */
Coffee coffee2 = new HouseBlend();
coffee2 = new Mocha(coffee2);
coffee2 = new Soy(coffee2);
coffee2 = new Milk(coffee2);
System.out.println(coffee2.getDescription() + " $" + coffee2.cost());
/** 客户点了一杯HouseBlend咖啡,两份Mocha调料。 */
Coffee coffee3 = new HouseBlend();
coffee3 = new Mocha(coffee3);
coffee3 = new Mocha(coffee3);
System.out.println(coffee3.getDescription() + " $" + coffee3.cost());
}
}
4. 运行结果