设计原则:对修改关闭,对扩展开放
以星巴克咖啡为例:
1.拿一个深咖啡对象(DarkRoast)
2.以摩卡(Mocha)对象装饰它
3.以奶泡(Whip)对象装饰它
4.调用cost()方法,并依赖委托将咖啡价格加上去
装饰者特点:
1.装饰者和被装饰者有相同的超类型
2.你可以用一个或多个装饰者装饰一个对象
3.既然装饰者和被装饰者有相同的超类型,所以在任何需要原始对象(被包装)的时候,可以用装饰过的对象代替它
4.装饰者可以在被装饰对象包装之前或之后,加上自己的行为,以达到特定的目的 (关键点)
5.对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用你喜欢的装饰者来装饰对象
装饰着模式:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案
public abstract class Beverage{
String description = "Unknown Beverage";
public abstract dobule coast();
public String getDescription(){
return description;
}
}
调料抽象类,也就是装饰者类:
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();//所有调料都必须重新实现该方法
}
饮料,浓缩咖啡
public class Espresso extends Beverage{
public Espresso(){
description = "Espresso";
}
public double cost(){
return 1.99;
}
}
public class HouseBlend extends Beverage{
public Espresso(){
description = "House Blend Coffee";
}
public double cost(){
return 0.89;
}
}
调料代码:也就是具体的装饰者
public class Mocha extends CondimentDecorator{
Beverage beverage;
public Mocha(Berverage berverage){
this.berverage = berverage;
}
public double cost(){
return 0.21 + berverage.coast();
}
public String getDescription(){
return berverage.getDescription() + ", Mocha";
}
}
测试代码:
public class StarbuzzCoffee{
public static void main(String[] str){
Berverage berverage = new Espresso();
System.out.println(berverage.getDescription()+" $"+berverage.cost());//要一杯Espresso,不要添加任何调料
Berverage berverage2 = new HouseBlend();
berverage2 = new Mocha(berverage2);
System.out.println(berverage2.getDescirpiton+" $"+berverage2.cost()); //来一杯HouseBlend,用Mocha泡过的
}
}
JDK中的装饰者模式
编写自己的装饰者:大写转成小写
public class LowerCaseInputStream extends FilterInputStream{
public LowerCaseeInputStream(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] = Character.toLowerCase((char)b[i]);
}
return result;
}
}
测试类:
public class InputTest{
public static void main(String[] str){
int c;
try{
InputStream c = 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();
}
}
}