首页 > 技术文章 > 设计模式之装饰者模式(Decorator)

limiracle 2014-08-12 12:41 原文

1、定义

装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案

2、类图

image

Component抽象构件:Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象。在装饰者模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件。

ConcreteComponent具体构件:ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。

Decorator装饰角色:一般是一个抽象类,实现接口或者抽象方法,它里面可不一定有抽象的方法,在它的属性里必然有一个private变量只想Component抽象构件。

ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,你要吧最核心的,最原始的东西装饰成其他东西。

3、实例介绍

咖啡计价描述,现有一coffee对象,有cost(),discription()两个方法,分别实现计价、描述。有需求新增一款咖啡,则有自己的cost()、discription()方法。但是现将所有coffee的配料全部添加摩卡,则所有coffee对象的discription()、cost()方法全部重写,添加摩卡。设计成装饰者模式,即可实现这种变化。

需求改为:现在有两款咖啡HouseBlend 、Espresso 。这两款coffee的配料主要有Mocha 、Whip 。但是这两种咖啡的配料会根据不同客户的需求改变。设计为观察者模式,最终使用配料来装饰咖啡。代码如下:

package decorator;
/**
 * Component抽象构件,定义最核心、最原始的对象
 */
public abstract class Beverage {
    String description="Unkown Beverage";
    public String getDescription(){
        return description;
    }
    public abstract double cost();
}
package decorator;

/**
 * ConcreteComponent具体构件,被修饰的对象
 */
public class HouseBlend extends Beverage{
    public HouseBlend(){
        description="House Blend Coffee";
    }
    public double cost(){
        return 0.89;
    }
}
package decorator;
/**
 * ConcreteComponent具体构件,被修饰的对象
 */
public  class Espresso extends Beverage{
    public Espresso(){
        description="Espresso coffee";
    }
    public double cost(){
        return 1.99;
    }
}
package decorator;
/**
 * Decorator 装饰角色,一般是一个抽象类,
 * 里面不一定有抽象方法,但会有一个变量指向Component抽象构件
 */
public abstract class CondimentDecorator extends Beverage{
    Beverage beverage;
    public abstract String getDescription();
}
package decorator;
/**
 * 具体装饰角色,继承ConcreteComponent
 */
public class Mocha extends CondimentDecorator{
    
    public Mocha(Beverage beverage){
        this.beverage=beverage;
    }
    public String getDescription(){
        return beverage.getDescription()+",Mocha";
    }
    public double cost(){
        return 0.20+beverage.cost();
    }
}
package decorator;
/**
 * 具体装饰角色,继承ConcreteComponent
 */
public class Whip extends CondimentDecorator{
    public Whip(Beverage beverage){
        this.beverage=beverage;
    }
    public String getDescription(){
        return beverage.getDescription()+",Whip";
    }
    public double cost(){
        return 0.20+beverage.cost();
    }
}
package decorator;

public class Main {
    public static void main(String args[]){
        //Espresso咖啡什么料都不加,所以不需要修饰
        Beverage beverage=new Espresso();
        System.out.println(beverage.getDescription()+" $ "+beverage.cost());
        //HouseBlend咖啡,加两份Mocha、一份Whip,
        Beverage beverage2=new HouseBlend();
        beverage2=new Mocha(beverage2);
        beverage2=new Mocha(beverage2);
        beverage2=new Whip(beverage2);
        System.out.println(beverage2.getDescription()+" $ "+beverage2.cost());
    }
}

装饰者模式在java API的java.io中大量引用,

image

缺点:

利用装饰者模式,常常造成设计中有大量小类。

推荐阅读