星巴兹咖啡准备更新订单系统,为的是不违背开放-关闭的设计原则:类应该对扩展开放,对修改关闭。
我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。
这个目标需要使用装饰者模式实现:以饮料为主体,然后运行调料来“装饰”饮料。
1.定义装饰者模式:2.把星巴兹咖啡系统进行修改,使其符合装饰者类图:
3.具体实现:
从饮料下手,将饮料作为一个抽象类:
package com.wk.cafe;
public abstract class Beverage {
String description = "Unkown Beverage";
public String getDescription(){
return description;
}
public abstract double cost();
}
调料抽象类,也就是装饰者类:
package com.wk.cafe;
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
实现具体的饮料:
package com.wk.cafe;
public class Espresso extends Beverage {
public Espresso(){
description = "Espresso";
}
public double cost(){
return 1.99;
}
}
package com.wk.cafe;
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "HouseBlend";
}
public double cost() {
return 0.89;
}
}
实现具体装饰者类:
package com.wk.cafe;
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 0.20+beverage.cost();
}
}
package com.wk.cafe;
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 0.20+beverage.cost();
}
}
package com.wk.cafe;
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 0.20+beverage.cost();
}
}
测试代码:
package com.wk.cafe;
public class StartbuzzCoffee {
public static void main(String args[]) {
Beverage beverage1 = new Espresso();
System.out.println(beverage1.getDescription() + " $"
+ beverage1.cost());
beverage1 = new Mocha(beverage1);
beverage1 = new Whip(beverage1);
System.out.println(beverage1.getDescription() + " $"
+ beverage1.cost());
Beverage beverage2 = new HouseBlend();
beverage2 = new Soy(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $"
+ beverage2.cost());
}
}
测试结果:
JAVA中的装饰者模式(java.io类):
Java I/O引出装饰者模式的一个“缺点”:利用装饰者模式,会造成设计中存在大量的小类。
我们可以编写自己的Java I/O装饰者(即ConcreteDecorator),它的作用是把输入流中的所有小写字母转成大写:
代码如下:
package com.wk.cafe;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class UpperCaseInputStream extends FilterInputStream {
protected UpperCaseInputStream(InputStream in) {
super(in);
// TODO Auto-generated constructor stub
}
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toUpperCase((char) c));
}
public int read(byte[] b, int offset, int len) throws IOException {
int result = super.read(b, offset, len);
for (int i = offset; i < offset + result; i++) {
b[i] = (byte) Character.toUpperCase((char) b[i]);
}
return result;
}
}
package com.wk.cafe;
import java.io.*;
public class UpperCaseInputStreamTest {
public static void main(String[] args) throws IOException {
int c;
try {
InputStream in = new UpperCaseInputStream(new BufferedInputStream(
new FileInputStream("E:\\inputtest.txt")));
while ((c = in.read()) >= 0) {
System.out.print((char) c);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}