背景介绍:星巴兹是一家很火爆的咖啡连锁店,因为扩张很快,需求多样化,原系统已不能满足。
原系统设计:
购买咖啡时,会要求加各种调料,系统要根据加的不同调料收取不同的费用,导致结构图如下:
解决方案:
以饮料为主体,然后运行时,以调料来“装饰”(decorate)饮料。
比如,顾客要加摩卡和奶泡的深焙咖啡。那么要做的是:
1.拿一个深焙咖啡(DarkRoast)对象
2.以摩卡(Mocha)对象装饰它
3.以奶泡(Whip)对象装饰它
4.调用cost()方法,并依赖委托(delegate)将调料的价钱加上去。
创建的图如下:
结算时,最外圈装饰者(Whip)的cost()就可以得到:
装饰者模式类图:
参照此类图,得到星巴兹饮料类图:
具体实现代码:
Beverage(饮料)
public abstract class Beverage {
public String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
装饰者类,Condiment(调料)
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
各种饮料
HouseBlend(综合咖啡)
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "HouseBlend";
}
public double cost() {
return .89;
}
}
Espresso(浓缩咖啡)
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
Decaf(低咖啡因)
public class Decaf extends Beverage {
public Decaf() {
description = "Decaf";
}
public double cost() {
return 1.05;
}
}
DarkRoast(深焙咖啡)
public class DarkRoast extends Beverage {
public DarkRoast() {
description = "DarkRoast";
}
public double cost() {
return .99;
}
}
各种调料
Mocha(摩卡)
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public double cost() {
return beverage.cost() + .20;
}
}
Soy(豆浆)
public class Soy extends CondimentDecorator {
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
return beverage.cost() + .30;
}
}
Whip(牛奶)
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public double cost() {
return beverage.cost() + .30;
}
}
测试:
public class StarbuzzCoffee {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage1 = new Mocha(new Mocha(new Whip(new DarkRoast())));
System.out.println(beverage1.getDescription() + " $" + beverage1.cost());
Beverage beverage2 = new Soy(new Mocha(new Whip(new DarkRoast())));
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
}
}
运行结果:
Java I/O流中的装饰者模式
编写自己的I/O装饰者,实现大小写转换
public class LowerCaseInputStream extends FilterInputStream {
public LowerCaseInputStream(InputStream in) {
super(in);
}
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toLowerCase((char)c));
}
public int read(byte b[], int off, int len) throws IOException {
int result = super.read(b, off, len);
for (int i = off; i < off + result; i++) {
b[i] = (byte) Character.toLowerCase((char)b[i]);
}
return result;
}
}
测试
public class InputTest {
public static void main(String[] args) {
int c;
try {
InputStream is = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
while ((c = is.read()) >= 0) {
System.out.print((char)c);
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果
总结:
装饰者模式--动态的将责任附加到对象上,想要扩展功能,装饰者提供有别于继承的另一种选择。