设计模式之装饰者模式

来源:互联网 发布:余罪小说知乎 编辑:程序博客网 时间:2024/06/08 09:35

某咖啡店因为扩张速度太快,需要更新订单系统

原先有一个Beverage(材料)抽象类,店内所提供的饮料都继承自它,有getDescription()、cost()和其他方法

有各种饮料,如HouseBlend,DarkRoast,Espresso等

而在购买咖啡时,也可以要求在其中加入各种调料,例如,Mocha,Soy,Whip等

这样一来组合就有很多种,如果每一种咖啡做成一个类,这简直就是类爆炸


有一个设计原则:类应该对扩展开放,对修改关闭


于是,我们可以使用Decorator Pattern,以饮料为主体,在运行时以调料来装饰饮料

比如,我想要一个加Mocha、Whip的DarkRoast咖啡,我们可以这么做:

1、拿一个DarkRoast对象

2、以Mocha对象装饰它

3、以Whip对象装饰它

4、调用cost()方法,并依赖委托(delegate)将调料的价钱加上去


上个类图:



代码:

从Beverage类下手

public abstract class Beverage {String description="Unknown beverage";public String getDescription(){return description;}public abstract double cost();}

Condiment抽象类,也就是装饰者类

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 DarkRoast extends Beverage{public DarkRoast(){description="DarkRoast";}public double cost(){return 1.11;}}

public class HouseBlend extends Beverage{public HouseBlend(){description="HouseBlend";}public double cost(){return .89;}}

实现具体装饰者,调料

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 .25+beverage.cost();}}

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 .20+beverage.cost();}}

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 .44+beverage.cost();}}

测试代码

public class Coffee {public static void main(String[]args){Beverage beverage=new Espresso();System.out.println(beverage.getDescription()+" $"+beverage.cost());Beverage beverage2=new DarkRoast();beverage2=new Mocha(beverage2);beverage2=new Soy(beverage2);beverage2=new Whip(beverage2);System.out.println(beverage2.getDescription()+" $"+beverage2.cost());Beverage beverage3=new HouseBlend();beverage3=new Soy(beverage3);beverage3=new Mocha(beverage3);beverage3=new Whip(beverage3);System.out.println(beverage3.getDescription()+" $"+beverage3.cost());}

结果

Espresso $1.99DarkRoast,Mocha,Soy,Whip $2.0HouseBlend,Soy,Mocha,Whip $1.78

----------------------------------------

其实IO就是装饰者

BufferedInputStream,LineNumberInputStream都扩展自FilterInputStream,而它就是一个抽象的装饰类


编写自己的IO装饰者

import java.io.FilterInputStream;import java.io.IOException;import java.io.InputStream;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;}}

import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;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();}}}

test.txt:I know the Decorator Pattern therefore I RULE!

结果:

i know the decorator pattern therefore i rule!

--------------------------------------- to conclude

Decorator Pattern动态的将责任附加到对象上,想要扩展功能,Decorator提供有别于继承的另一种选择。

在我们的设计中,应该允许行为可以被扩展,而无须修改现有的代码。

Decorator会导致设计中出现许多小对象,如果过度使用,会让程序变得复杂。

0 0
原创粉丝点击