星空网 > 软件开发 > ASP.net

第三章:装饰器模式

这章用星巴克咖啡店的例子演示了装饰器模式的使用。

先来看看在星巴克点咖啡的场景:在星巴克你先要点一种饮料,然后你可以加入各种调料(调料也要钱)。

比如:来一份综合咖啡(House Blend),加一份摩卡,再加一份豆浆。那么一共0.89+0.2+0.15=1.24美元。

在比如:来一份综合咖啡,加两份摩卡(我太喜欢摩卡了),再加一份奶泡。

第三章:装饰器模式

 

下面用装饰模式来实现

调料可以看做一种装饰器,装饰在饮料上面。下面是装饰器模式实现星巴克的UML图。

考虑下面的问题:

  • 令人奇怪的是为什么调料要继承自饮料,装饰器模式必须要求装饰器是被装饰者的子类。你现在肯定对此很不解,下文贴出了main函数代码,仔细阅读main函数你应该能明白为什么。
  • 为什么装饰器要有beverage字段?即,为什么装饰器要记住自己装饰的是哪个对象?

第三章:装饰器模式

先看看客户端生产咖啡的代码。真的是太巧妙了,你可以任意添加各种调料。

public class Client {  public static void main(String[] args) {    //综合咖啡 + 摩卡 + 豆浆    Beverage beverage1 = new HouseBlend();    beverage1 = new Mocha(beverage1); //你看,如果调料不是饮料的子类,该语句就出错了     beverage1 = new Soy(beverage1);    System.out.println(beverage1.getDescription() + " $:" + beverage1.cost());        //综合咖啡 + 摩卡 + 摩卡 + 奶泡    Beverage beverage2 = new HouseBlend();    beverage2 = new Mocha(beverage2);    beverage2 = new Mocha(beverage2);    beverage2 = new Whip(beverage2);    System.out.println(beverage2.getDescription() + " $:" + beverage2.cost());  }}

输出结果是:

综合咖啡,摩卡  $:1.24
综合咖啡,摩卡  $:1.3900000000000001

实现代码:

//饮料,是抽象类public abstract class Beverage {  protected String description = "不知道是什么饮料";    public String getDescription() {    return description;  }    public abstract double cost();}//调料(装饰器)。要继承自饮料。虽然调料继承自饮料有点奇怪,但装饰器模式必须要这样。public abstract class CondimentDecorator extends Beverage {  Beverage beverage;    public CondimentDecorator(Beverage beverage) {    this.beverage = beverage;      }}//综合咖啡,是一种饮料。public class HouseBlend extends Beverage {  public HouseBlend() {    description = "综合咖啡";  }    @Override  public double cost() {    return 0.89;  }}//摩卡,是一种调料。价格0.2美元。public class Mocha extends CondimentDecorator {  public Mocha(Beverage beverage) {    super(beverage);    this.beverage.description += ",摩卡"; //此处代码易错,见下面的错误代码演示  }    @Override  public String getDescription() {    return this.beverage.getDescription(); //此处代码易错,见下面的错误代码演示  }    @Override  public double cost() {    return beverage.cost() + 0.2;  }}

错误代码演示

//这段代码错在description字段//Whip自己也从基类继承了description字段//beverage也有一个description字段//仔细想想到底应该改变哪个字段的值???public class Whip extends CondimentDecorator {  Beverage beverage;  public Whip(Beverage beverage) {    this.beverage = beverage;    description += ", 奶泡";  }  @Override  public double cost() {    return beverage.cost() + 0.3;  }}

//这段代码改进了上面提到的错误,但是还有一处错误,你仔细想想看吧!//Soy从基类继承了getDescription()方法//beverage也有getDescription()方法//想想我们到底应该调用谁的getDescription()方法???//那么看来Soy必须override getDescription()方法,并在其中调用beverage的getDescription()方法。public class Soy extends CondimentDecorator {  Beverage beverage;  public Soy(Beverage beverage) {    this.beverage = beverage;    this.beverage.description += ", 豆浆";  }  @Override  public double cost() {    return beverage.cost() + 0.1;  }}

扩展练习

如果想把星巴克的咖啡带回办公室享受,那么需要支付打包费用。因为杯子要钱,杯子还分豪华杯子和简陋的杯子。我也不知道杯子有什么区别,也许豪华的可以保温吧- -。我扩展了下面这个类图,你可以用Java实现一下。

另外,也许有人觉得调料是饮料的子类并不奇怪(也有人把调料当饮料喝)。但是下面这个类图杯子竟然是饮料的子类!!!不要怀疑,装饰器模式就是这样的~~~

第三章:装饰器模式




原标题:第三章:装饰器模式

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

TikTok Shop将败走印尼?将效仿印度美国封禁令,印尼要干嘛?:https://www.goluckyvip.com/news/12978.html
Shopee一店通:https://www.goluckyvip.com/news/1298.html
Shopee惩罚扣分规则变了,小心被扣分:https://www.goluckyvip.com/news/1299.html
黄金周电商流量环比大降 快递未见爆仓个别微降:https://www.goluckyvip.com/news/13.html
亚马逊Prime Day期间物流超负荷,或将影响所有卖家订单配送!:https://www.goluckyvip.com/news/130.html
韩国&尼日利亚电商政策与海关程序解读_贸易国电商政策案例分析:https://www.goluckyvip.com/news/1300.html
NRA账户的开户主体包括:香港、美国、新加坡、欧盟等国家的详细解析 :https://www.xlkjsw.com/news/94338.html
湘西游轮六 湘江游轮夜游:https://www.vstour.cn/a/411226.html
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流