设计模式笔记:装饰者模式

概念

装饰者模式,又叫装饰模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

组成

应用场景

优缺点

优点

缺点

应用举例

Starbuzz是以扩张速度最快而闻名的咖啡连锁店。因为扩张速度实在太快了,他们准备更新订单系统,以合乎他们对饮料供应要求。

他们原先的设计是这样的:

购买咖啡时,也可以要求在其中加入各种调料,例如:豆浆、摩卡、牛奶或着奶泡。Starbuzz会根据所加入的调料收取不同的费用。

如果简单使用继承:

使用装饰者模式

Beverage抽象类

public abstract class Beverage{
    String description = "Unknown Beverage";
    
    public String getDescription(){
        return description;
    }
    
    // 所有子类都必须实现该方法
    public abstract double cost();

}

CondimentDecorator抽象类

public abstract class CondimentDecorator extends Beverage{
    // 所有调料装饰者都必须实现该方法
    public abstract String getDescription();
}

具体Beverage类

下面创建了Espresso和HouseBlend两个示例,其余具体的Beverage也可以参照此方法实现,比如DarkRoast。

public class Espresso extends Beverage{
    
    public Espresso(){
        despcription = "Espresso";
    }
    
    public double cost(){
        return 1.99;
    }
}

public class HouseBlend extends Beverage{
    
    public HouseBlend(){
        description = "HouseBlend";
    }
    
    public double cost(){
        return 0.89;
    }
}

具体CondimentDecorator类

下面是Mocha示例,其余具体的CondimentDecorator也可以参照此方法实现,比如Whip和Soy。

// Mocha是一个装饰者,所以继承自CondimentDecorator
public class Mocha extends CondimentDecorator{

    // 引用一个具体的Beverage类,用来表示被装饰者
    Beverage beverage;
    
    public Mocha(Beverage beverage){
        this.beverage = beverage;
    }
    
    // 为被装饰者装饰服务
    public String getDescription(){
        return beverage.getDescription() + ", Mocha";
    }
    
    // 要计算带Mocha的饮料价钱,首先把调用委托给被装饰对象,以计算价钱
    // 然后再加上Mocha的价钱,得到最后的结果
    public double cost(){
        return 0.20 + beverage.cost();
    }
}

供应咖啡

public class StarbuzzCoffee{

    public static void main(String[] args){
        // 订一杯Espresso,不需要调料
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());
        
        // 订一杯DarkRoast,加Whip和双倍Mocha的
        Beverage beverage2 = new DarkRoast();
        beverage2 = new Mocha(beverage2);
        bevearge2 = new Mocah(beverage2);
        beverage2 = new Whip(beverage2);
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
        
        // 再来一杯HouseBlend,加Soy、Mocha和Whip
        Beverage beverage3 = new HouseBlend();
        beverage3 = new Soy(beverage3);
        bevearge3 = new Mocah(beverage3);
        beverage3 = new Whip(beverage3);
        System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
    }
}

运行程序

%java Starbuzz

Espresso $1.99
Dark Roast Coffee, Mocha, Mocha, Whip $1.49
House Blend Coffee, Soy, Mocha, Whip $1.34