java设计模式--装饰者模式

来源:互联网 发布:便携式移动数据采集器 编辑:程序博客网 时间:2024/06/11 01:26

装饰者模式

假设给我个题目,现在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 Blend1.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());    }}/*OutputEspresso $1.99Dark Roast Coffee, Mocha, Mocha, Whip $1.49House 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();        }    }}

参考文献

  1. Head First Design Pattern
  2. 大话设计模式
  3. Thinking in Java
0 0
原创粉丝点击