装饰者模式

简介

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

类图

Componet
avatar
每个组件(ConcreteComponent)都可以单独使用,或者被装饰者包起来使用

实现

定义抽象组件(超类)

package decorate;

/**
 * 超类:抽象组件
 */
public abstract class Beverage {

    /**
     * 饮料描述
     * @return
     */
    String description = "Unknown Beverage";

    public String getDescription(){return description;}

    /**
     * 饮料价钱
     * @return
     */
    public abstract double cost();
}

定义装饰者抽象类

package decorate;

/**
 * 抽象装饰者
 * 装饰者抽象类
 */
public abstract class CondimentDecorator extends Beverage{

    public abstract String getDescription();

}

创建三种被装饰者(具体组件)

package decorate;

/**
 * 具体组件
 * 扩展自Beverage,因为是饮料:另一种咖啡
 */
public class DarkRoast extends Beverage {

    /**
     * 设置饮料描述
     */
    public DarkRoast(){
        description = "Dark Roast Coffee";
    }

    public double cost(){
        return 0.99;
    }

}

另一个被装饰者

package decorate;

/**
 * 具体组件
 * 扩展自Beverage,因为是饮料:浓缩咖啡
 */
public class Espresso extends Beverage {

    /**
     * 设置饮料描述
     */
    public Espresso(){
        description = "Espresso";
    }

    public double cost(){
        return 1.99;
    }

}

另一个被装饰者

package decorate;

/**
 * 具体组件
 * 另一种饮料:综合咖啡
 */
public class HouseBlend extends Beverage{

    public HouseBlend(){
        description = "House Blend Coffee";
    }

    public double cost(){
        return 0.89;
    }

}

创建三种装饰者(具体装饰者)

package decorate;

/**
 * 具体装饰者,扩展自装饰者抽象
 * 摩卡
 */
public class Mocha extends CondimentDecorator {
    //用一个实例变量记录饮料
    Beverage beverage;

    /**
     * 让被装饰者(饮料)当作构造器的参数被记录到实例变量
     * @param beverage 被装饰者
     */
    public Mocha(Beverage beverage){
        this.beverage = beverage;
    }

    /**
     * 完成描述饮料及调料
     */
    @Override
    public String getDescription(){
        return beverage.getDescription() + ",Mocha";
    }

    /**
     * 调用被装饰对象cost以计算价钱,然后再加上mocha的价钱,得到最后结果
     */
    @Override
    public double cost() {
        return 0.20+beverage.cost();
    }
}

另一个装饰者

package decorate;

/**
 * 另一个装饰者(调料)
 */
public class Soy extends CondimentDecorator{
    private Beverage beverage;

    public Soy(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public double cost() {
        return 0.5+beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Soy";
    }
}

另一个装饰者

package decorate;

/**
 * 另一个装饰者(调料)
 */
public class Whip extends CondimentDecorator{
    private Beverage beverage;

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public double cost() {
        return 0.9+beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Whip";
    }
}

测试装饰者模式

package decorate;

/**
 * 测试装饰者模式
 * 组件(咖啡)+各种装饰者(调料)
 */
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());
	}
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!