设计模式之装饰者模式

来源:互联网 发布:步态分析数据 编辑:程序博客网 时间:2024/06/05 13:10

装饰者模式

        在《Head First 设计模式》一书中,对于装饰者模式的讲解是以一个咖啡店的饮料为模型来展开讲解的。在我们购买咖啡时会选择加入各种各样的调料,例如:蒸奶、豆浆、摩卡或奶泡等。每种咖啡也会根据所加入的调料不同收取相应的费用。一个比较成熟的设计方案是:以饮料为主体,然后在运行时以调料来"装饰(decorate)"饮料。比如:如果顾客想要摩卡和奶泡深焙咖啡,那么做法是:
1.拿一个深焙咖啡(DarkRoast)对象
2.以摩卡(Mocha)对象装饰它
3.以奶泡(Whip)对象装饰它
4.调用cost()方法,并依赖委托(delegate)将调料的价钱加上去

从中可以看出:
1.装饰者和被装饰者对象有相同的超类型
2.你可以用一个或多个装饰者包装一个对象
3.既然装饰者和被装饰者对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它 。
4.装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
5.对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者类图:

星巴兹代码:

Beverage类:
package com.my.strategy;public abstract class Beverage {    String description = "Unknown Beverage";    public String getDescription() {        return description;    }    public abstract double cost();}
CondimentDecorator类:
package com.my.strategy;public abstract class CondimentDecorator extends Beverage{    public abstract String getDescription();}
Espresso类:
package com.my.strategy;public class Espresso extends Beverage {//让Espresso继承自Beverage,                                        // 因为Espresso是一种饮料    public Espresso(){        //description继承自Beverage        description = "Espresso";    }    public double cost(){        return 1.99;    }}
另一种饮料:
package com.my.strategy;public class HouseBlend extends Beverage {    public HouseBlend(){        description = "House Blend Coffee";    }    public double cost(){        return .89;    }}
Mocha类:
package com.my.strategy;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();    }}

Main:

package com.my.strategy;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);//用Mocha装饰它        beverage2 = new Mocha(beverage2);//用Mocha装饰它        beverage2 = new Whip(beverage2);//用Whip装饰它        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());    }}

Run: