【设计模式】一文彻底搞懂装饰器(Decorator)设计模式

网上关于装饰器(decorator)模式的教程很多,但是很少有能讲的很清楚的,所以有了这篇文章。

在讲解装饰器模式之前,先看看为什么要使用装饰器模式。

假设我们要为一个咖啡馆设计一套下单和结算系统,咖啡管的产品有茶,咖啡,橙汁三种产品,售价分别为5,10,15, 客人可以在饮料中加入一些搭配,比如咖啡可以加奶、加糖,橙汁可以加冰,茶也可以加奶。假设客人需要付费才能加配料。那我们先来思考一下如何设计这么一个系统,一个朴素的想法就是用组合模式,请看下面的uml图。

在每个饮料的基类中放一个List<Add> 表示附加的东西。来看看这么设计的问题:

  • 如果我们规定了茶里面就是不能加糖的,这种组合无效。
  • 假设我们有一天突发奇想,发明了一种新的饮料,咖啡+茶,那么这种设计显然不够灵活。

为了解决第二个问题,我们将所有的Berverage 和 add进行组合,枚举所有的产品,这显然不可行。

于是我们有了装饰器模式。请看下面的UML图:

这里的核心思想是:所有的饮料子类和附件类  既是Berverage,也包含一个Berverage,这一点非常重要,是装饰器模式的核心思想,子类 has-a 并且 is-a 父类。

来看看代码

public interface IBeverage {
    public String getDescription();
    public int cost();
}

public class Coffee implements IBeverage {
    @Override
    public String getDescription() {
        return "to Coffee";
    }

    @Override
    public int cost() {
        return 12;
    }
}
public class Tea implements IBeverage {
    @Override
    public String getDescription() {
        return " to Tea";
    }

    @Override
    public int cost() {
        return 10;
    }
}
// decorator not only is a kind of beverage, but has a kinds of beverage. The beverage addon decorator itself can wrap
// outside the beverage it contains. The beverage it contains can also wrap around some other beverage inside it,
// layer by layer
public class AddMilkDecorator implements IBeverage {
    private  IBeverage beverage;

    public AddMilkDecorator(IBeverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return "add some milk" + this.beverage.getDescription();
    }

    @Override
    public int cost() {
        return 5+this.beverage.cost();
    }
}
public class AddSugarDecorator implements IBeverage  {
    private IBeverage beverage;

    public AddSugarDecorator(IBeverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return "Add sugar" + this.beverage.getDescription();
    }

    @Override
    public int cost() {
        return 3 + this.beverage.cost();
    }
}
public class Client {

    public static void main(String[] args){
        IBeverage beverage = new AddMilkDecorator(new AddMilkDecorator(new AddSugarDecorator(new Coffee())));
        System.out.println("Your order is " + beverage.getDescription());
        System.out.println("This beverage and addons totally costs"+beverage.cost());
    }
}

好了,先就讲这么多,总之只要记住:子类既is-a基类又has-a基类

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值