本文出自 http://blog.csdn.net/shuangde800
认识装饰者模式
在星巴克购买咖啡时,可以根据自己的要求,加入各种调料,例如:蒸奶、豆浆、摩卡或覆盖奶泡。星巴克会根据所加入的调料收取不同的费用。
如何设计这个类?
用装饰者模式,我们将以饮料为主体,然后再运行时以各种调料来“装饰”饮料。比如说,顾客想要摩卡和奶泡深焙咖啡:
1、拿一杯深焙咖啡作为主体对象
2、以摩卡对象装饰它
3、以奶泡对象装饰它
4、调用cost方法计算出总价钱。
定义装饰者模式
装饰者模式是动态地将责任附加到对象上。若要拓展功能,装饰者模式提供了比继承更有弹性的替代方案。
类图
用装饰者模式的Java I/O:
java中的I/O的设计中大量的用到了装饰模式
BufferedInputStream 及LineNumberInputStream都拓展自FilterInputStream,而FilterInputStream是一个抽象的装饰类
装饰java.io类
“输出流”的设计方式也是一样的。
编写自己的Java I/O装饰者:
编一个装饰者,把输入流内的所有大写字符转成小写、
package headfirst.decorator.io;
import java.io.*;
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 offset, int len) throws IOException {
int result = super.read(b, offset, len);
for (int i = offset; i < offset+result; i++) {
b[i] = (byte)Character.toLowerCase((char)b[i]);
}
return result;
}
}
测试类:
package headfirst.decorator.io;
import java.io.*;
public class InputTest {
public static void main(String[] args) throws IOException {
int c;
try {
InputStream in =
new LowerCaseInputStream(
new BufferedInputStream(
new FileInputStream("test.txt")));
while((c = in.read()) >= 0) {
System.out.print((char)c);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
缺点
但是Java I/O也引出装饰者模式的一个“缺点”:利用装饰者模式,常常照成设计中有大量的小类,数量是在是太多,可能会照成使用此API程序员的困扰。
但是,了解了装饰者的工作原理,以后使用别人的大量装饰的API时,就可以很容易地辨识出他们的装饰者类是如何组织的,以方便用包装方式取得想要的行为。
设计原则
开放-关闭原则:类应该对拓展开放,对修改关闭
设计的目标是允许类容易拓展,在不修改现有代码的情况下,就可搭配新的行为。