java设计模式--装饰者模式
2015-05-15 14:56
465 查看
装饰者模式
假设给我个题目,现在Coffe bar 有四种beverage,such as HouseBlend(0.89$$),Dark Roast(0.99$), Espreso(1.99$), Decaf(1.05$),供我选择,每种beverage,你可以选择加Milk(0.1$),Mocha(0.2$),Soy(0.15$),Whip(0.2$),要我来设计一个程序来实现。于是我就码出了如下程序:
package Decorator; public abstract class Beverage { String description = "Unknown Beverage"; private boolean milk=false; private boolean mocha=false; private boolean soy=false; private boolean whip=false; public boolean hasMilk(){ return milk; } public void setMilk(boolean milk){ this.milk = milk; } public boolean hasMocha(){ return mocha; } public void setMocha(boolean mocha){ this.mocha = mocha; } public boolean hasSoy(){ return soy; } public void setSoy(boolean Soy){ this.soy = Soy; } public boolean hasWhip(){ return whip; } public void setWhip(boolean Whip){ this.whip = Whip; } public String getDescription() { return description; } public double cost(){ double condimentCost = 0.0; if(hasMilk()){ condimentCost+=0.1; } if(hasMocha()){ condimentCost+=0.2; } if(hasSoy()){ condimentCost+=0.15; } if(hasWhip()){ condimentCost+=0.1; } return condimentCost; } }
package Decorator; public class DarkRoast extends Beverage { public DarkRoast(){ description = "Most Excellent Dark Roast"; } public double cost(){ return 0.99+super.cost(); } } package Decorator; public class Decaf extends Beverage{ public Decaf(){ description = "Most Excellent Decaf"; } public double cost(){ return 1.05+super.cost(); } } package Decorator; public class Espresso extends Beverage{ public Espresso(){ description = "Most Excellent Espresso"; } public double cost(){ return 0.99+super.cost(); } } package Decorator; public class HouseBlend extends Beverage{ public HouseBlend(){ description = "Most Excellent House Blend"; } public double cost(){ return 0.89+super.cost(); } }
package Decorator; public class Client { public static void main(String[] args) { Beverage bg = new HouseBlend(); bg.setMilk(true);//add milk bg.setMocha(true);//add mocha System.out.println(bg.getDescription()); System.out.println(bg.cost()); } }/* Most Excellent House Blend 1.19 */
piece of cake!!
不过转念一想,如果我想再加上一种原料,是不是就有点麻烦了!比如honey(0.1$),这时我就要手动修改beverage这个类了,貌似麻烦了一点;
package Decorator; public abstract class Beverage { String description = "Unknown Beverage"; private boolean milk=false; private boolean mocha=false; private boolean soy=false; private boolean whip=false; private boolean honey=false; public boolean hasMilk(){ return milk; } public void setMilk(boolean milk){ this.milk = milk; } public boolean hasMocha(){ return mocha; } public void setMocha(boolean mocha){ this.mocha = mocha; } public boolean hasSoy(){ return soy; } public void setSoy(boolean Soy){ this.soy = Soy; } public boolean hasWhip(){ return whip; } public void setWhip(boolean Whip){ this.whip = Whip; } public boolean hasHoney(){ return honey; } public void setHoney(boolean honey){ this.honey= honey; } public String getDescription() { return description; } public double cost(){ double condimentCost = 0.0; if(hasMilk()){ condimentCost+=0.1; } if(hasMocha()){ condimentCost+=0.2; } if(hasSoy()){ condimentCost+=0.15; } if(hasWhip()){ condimentCost+=0.1; } if(hasHoney()){ condimentCost+=0.1; } return condimentCost; } }
如果我有上百种原料,想一想,beverage这个类肯定会更复杂,且不符合抽象的原则。那应该怎么办呢?
想到这里我们第一反应就是这些原料最好继承某个基类,这样可以方便添加;那原料和beverage怎么关联呢? 就产生了下图那个装饰者模式的基本形式,beverage类可以灵活的添加原料
所有的ConcreteDecorator类似 于这里的原料均继承于Decorator这个抽象类,这个抽象类又继承于beverage这个基类。
如下图:
package headfirst.decorator.starbuzz; public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); }
package headfirst.decorator.starbuzz; public class DarkRoast extends Beverage { public DarkRoast() { description = "Dark Roast Coffee"; } public double cost() { return .99; } }
package headfirst.decorator.starbuzz; public class Decaf extends Beverage { public Decaf() { description = "Decaf Coffee"; } public double cost() { return 1.05; } }
package headfirst.decorator.starbuzz; public class Espresso extends Beverage { public Espresso() { description = "Espresso"; } public double cost() { return 1.99; } }
package headfirst.decorator.starbuzz; public class HouseBlend extends Beverage { public HouseBlend() { description = "House Blend Coffee"; } public double cost() { return .89; } }
package headfirst.decorator.starbuzz; public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
package headfirst.decorator.starbuzz; public class Milk extends CondimentDecorator { Beverage beverage; public Milk(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", Milk"; } public double cost() { return .10 + beverage.cost(); } }
package headfirst.decorator.starbuzz; 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(); } }
package headfirst.decorator.starbuzz; 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 .15 + beverage.cost(); } }
package headfirst.decorator.starbuzz; 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 .10 + beverage.cost(); } }
package headfirst.decorator.starbuzz; public class StarbuzzCoffee { 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 Mocha(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()); } }/*Output Espresso $1.99 Dark Roast Coffee, Mocha, Mocha, Whip $1.49 House Blend Coffee, Soy, Mocha, Whip $1.34 */
这时我想扩充原料的类型时,我只有再继承一个原料类就可以了,比如Honey(0.1$)
package headfirst.decorator.starbuzz; public class Honey extends CondimentDecorator { Beverage beverage; public Whip(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", Honey"; } public double cost() { return .10 + beverage.cost(); } }
装饰者模式在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(); } } }
参考文献
Head First Design Pattern大话设计模式
Thinking in Java
相关文章推荐
- JAVA设计模式之装饰者模式
- java设计模式之装饰者模式
- Java设计模式之装饰者模式
- java设计模式---装饰者设计模式
- JAVA设计模式初探之装饰者模式
- JAVA 设计模式 装饰者模式
- java常用设计模式(装饰者模式)
- JAVA设计模式初探之装饰者模式
- Java设计模式之装饰者模式
- JAVA设计模式初探之装饰者模式
- JAVA系列-设计模式-装饰者模式
- java设计模式-装饰者模式
- 设计模式(三)装饰者模式之java.io
- JAVA设计模式初探之装饰者模式
- java设计模式------装饰者模式
- Java设计模式透析--装饰者模式(二)
- java设计模式之装饰者模式
- Java常用GoF设计模式之一装饰者模式
- java设计模式----装饰者模式
- Java 设计模式(二) 装饰者模式