HeadFirst设计模式-装饰者模式(中)

接上文。

我们知道,利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

这里引出一个很重要的设计原则,开闭原则

设计原则

类应该对扩展开放,对修改关闭。

我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。这样的设计具有弹性,可以应对改变,可以接收新的功能来应对改变的需求。

下面来看用装饰者模式是如何实现开闭原则的。

装饰者模式方案

我们已经了解利用继承无法完全解决问题,所以,这里采用不一样的做法:我们要以饮料为主体,然后在运行时以调料来装饰(decorate)饮料。比方说,如果顾客想要摩卡和奶泡深培咖啡,那么要做的是:

1、拿一个深培咖啡(DarkRoast)对象

2、以摩卡(Mocha)对象装饰它

3、以奶泡(Whip)对象装饰它

4、调用cost()方法,并依赖委托(delegate)将调料的价钱加上去。

代码展示,先从Beverage类下手,这不需要改变最原始的设计。

public abstract class Beverage {
    String description = "Unknown Beverage";
    
    public String getDescription() {
        return desciption;
    }
    
    public abstract double cost();
}

调料抽象类Condiment,也就是装饰者类

public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}

饮料的代码

public class Espresso extends Beverage {
    
    public Espresso() {
        description = "Espresso";
    }
    
    public double cost() {
        // 不需要管调料的价钱,直接把Espresso的价格返回即可。
        return 1.99;
    }
}

调料的代码

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 0.20 + beverage.cost();
    }
}

下订单的测试代码

public static void main(String args[]) {
    // 订一个双倍摩卡奶泡深培
    Beverage beverage = new DarkRoast();
    beverage = new Mocha(beverage);
    // 用第二个Mocha装饰它
    beverage = new Mocha(beverage);
    beverage = new Whip(beverage);
    System.out.println(beverage.cost());
}

以上就是用装饰者模式实现的咖啡店的方案。看Java里哪些类实现了装饰者模式,请看《HeadFirst设计模式-装饰者模式(下)》

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值