1 装饰者模式的定义和特点

1.1什么是装饰者模式

书中解释: 动态的将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一种选择。
一句化解释: 不改变对象的情况下,动态对对象功能进行扩展。完美的诠释了开闭原则。

1.2 装饰者模式特点

被装饰者抽象角色: 被装饰者有那些功能
被装饰者角色: 被装饰者功能的具体实现
装饰者角色: 装饰 被装饰者的角色 装饰者持有被装饰者抽象角色。

3 装饰者模式要点和设计原则

3.1设计原则

多用组合少用继承
针对接口编程,不针对实现编程
类应该对外扩展开放,对修改关闭 (开闭原则)

3.2 装饰者模式要点

  • 继承可以进行扩展,但不是最佳弹性设计的方式
  • 应该允许行为可以扩展,而且无需修改现有的代码
  • 组合和委托可以在运行时加上新的行为
  • 装饰是除了继承的另外一种扩展方式
  • 装饰者就是一群装饰类去包装一个组件
  • 装饰者和被装饰着应该是相同类型
  • 装饰者可以对被装饰者添加自己的行为
  • 装饰者会导致设计中出现很多小对象,如果多度使用,会让程序变得很复杂

2 书中代码优化案例演进

书中通过介绍星巴克 各种饮料和调料组成不同的新饮料和价格的变化的案例来一步步演示如何优化成装饰者模式的方案。

2.1第一个版本代码和类图

第一版本代码中不同的调料配合我们可以组成上千中饮料 我们需要写上千个类,写着写着你就疯了

类图

具体的代码

饮料的抽象类

package cn.zhuoqianmingyue.decorator.first;/*** 饮料 抽象类*/
public abstract class Beverage {private  String description;public String getDescription(){return  description;}public void setDescription(String description){this.description = description;}public abstract double cost();
}

具体的饮料类 脱脂蒸奶

package cn.zhuoqianmingyue.decorator.first;/*** 脱脂蒸奶*/
public class DeacfSteamedMilk extends Beverage{public DeacfSteamedMilk(){setDescription("脱脂蒸奶");}@Overridepublic double cost() {return 30d;}
}

具体的饮料类 脂豆浆

package cn.zhuoqianmingyue.decorator.first;/*** 脱脂豆浆*/
public class DecafWithSoy  extends Beverage{public DecafWithSoy(){setDescription("脱脂豆浆");}@Overridepublic double cost() {return 15d;}
}

测试类

package cn.zhuoqianmingyue.decorator.first;/*** 不同的调料配合我们可以组成上千中饮料 我们需要写上千个类,写着写着你就疯了*/
public class Application {public static void main(String[] args){Beverage deacfSteamedMilk = new DeacfSteamedMilk();double cost = deacfSteamedMilk.cost();System.out.println(deacfSteamedMilk.getDescription()+"需要"+cost);Beverage decafWithSoy = new DecafWithSoy();double cost2 = decafWithSoy.cost();System.out.println(decafWithSoy.getDescription()+"需要"+cost2);}
}

2.2第2个版本代码和类图

第2版本代码虽然大大减少类的数量但是不能解决下面的问题:

  • 这个方式改变调料的价钱需要我们修改Beverage类中的源代码
  • 一旦添加新的调料要在修改Beverage的cost方法
  • 添加新的调料并不适合新的饮料
  • 无法满足客户想要加双倍的摩卡

类图

具体的代码

饮料的抽象类

package cn.zhuoqianmingyue.decorator.second;/*** 饮料 抽象类*/
public abstract class Beverage {private String description;private Boolean milk =false;//是否加奶private Boolean soy =false;//是否加豆浆private Boolean mocha =false;//是否夹摩卡private Boolean whip =false;//是否夹奶泡double milkCost = 3d;double soyCost = 4d;double mochaCost =5d;double whipCost =6d;public String getDescription(){return  description;}public void setDescription(String description){this.description = description;}public  double cost(){double condimentCost = 0.0d;if(hasMilk()){condimentCost += milkCost;}if(hasSoy()){condimentCost += soyCost;}if(hasMocha()){condimentCost += mochaCost;}if(hasWhip()){condimentCost += whipCost;}return condimentCost;}public Boolean hasMilk() {return milk;}public void setMilk(Boolean milk) {this.milk = milk;}public Boolean hasSoy() {return soy;}public void setSoy(Boolean soy) {this.soy = soy;}public Boolean hasMocha() {return mocha;}public void setMocha(Boolean mocha) {this.mocha = mocha;}public Boolean hasWhip() {return whip;}public void setWhip(Boolean whip) {this.whip = whip;}
}

具体的饮料类

package cn.zhuoqianmingyue.decorator.second;public class DarkRoast extends Beverage{@Overridepublic double cost() {return super.cost()+1.99d;}
}
package cn.zhuoqianmingyue.decorator.second;public class Decaf extends Beverage {@Overridepublic double cost() {return super.cost()+2.99d;}
}

具体的饮料类

package cn.zhuoqianmingyue.decorator.second;public class HouseBleand extends Beverage{@Overridepublic double cost() {return super.cost()+3.99d;}
}

测试类

package cn.zhuoqianmingyue.decorator.second;/*** 这个方式改变调料的价钱需要我们修改Beverage类中的源代码* 一旦添加新的调料要在修改Beverage的cost方法* 添加新的调料并不适合新的饮料* 无法满足客户想要加双倍的摩卡*/
public class Application {public static void main(String[] args){Beverage darkRoastarkRoast = new DarkRoast();darkRoastarkRoast.setMilk(true);darkRoastarkRoast.setSoy(true);double cost = darkRoastarkRoast.cost();System.out.println(cost);}
}

2.3第3个版本代码和类图

这个版本采用装饰者模式。

类图

具体的代码

饮料的抽象类

package cn.zhuoqianmingyue.decorator.third;public abstract class Beverage {String description = "不知道是什么饮料";public String getDescription(){return description;}public abstract double cost();
}

调料的抽象类

package cn.zhuoqianmingyue.decorator.third;/*** 调料的抽象类*/
public abstract  class CondimentDecorator extends Beverage {public abstract String getDescription();
}

被装饰的饮料类: 浓缩咖啡

package cn.zhuoqianmingyue.decorator.third;public class Espresso extends Beverage {public Espresso(){description = "浓缩咖啡";}@Overridepublic double cost() {return 1.99d;}
}

被装饰的饮料类: 综合咖啡

package cn.zhuoqianmingyue.decorator.third;public class HouseBlend extends Beverage {public HouseBlend(){description = "综合咖啡";}@Overridepublic double cost() {return 0.89d;}
}

装饰调料类: 加摩卡

package cn.zhuoqianmingyue.decorator.third;public class Mocha extends CondimentDecorator {Beverage beverage;public Mocha(Beverage beverage){this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription()+"加摩卡";}@Overridepublic double cost() {return 0.20+beverage.cost();}
}

装饰调料类: 加奶泡

package cn.zhuoqianmingyue.decorator.third;public class Whip extends CondimentDecorator {Beverage beverage;public Whip(Beverage beverage){this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription()+"加奶泡";}@Overridepublic double cost() {return beverage.cost()+ 0.5d;}
}

测试类

package cn.zhuoqianmingyue.decorator.third;public class Application {public static void main(String[] args){Beverage espresso = new Espresso();System.out.println(espresso.getDescription() + "$ " + espresso.cost());Beverage houseBlend = new HouseBlend();houseBlend = new Mocha(houseBlend);System.out.println(houseBlend.getDescription() + "$ " + houseBlend.cost());Beverage houseBlend2 = new HouseBlend();houseBlend2 = new Whip(houseBlend);System.out.println(houseBlend2.getDescription() + "$ " + houseBlend2.cost());}
}

【Head First 设计模式】-装饰者模式读后总结相关推荐

  1. Python设计模式-装饰器模式

    Python设计模式-装饰器模式 代码基于3.5.2,代码如下; #coding:utf-8 #装饰器模式class Beverage():name = ""price = 0.0 ...

  2. 设计模式——装饰者模式

    本文是阅读 Head First 设计模式--装饰者模式的总结. 这本书的教学模式很不错,个人很喜欢,由实际的案例由浅入深,循序渐进的让你明白良好的设计是多么的优雅迷人(回头看看自己的代码,WTF!) ...

  3. 10. 设计模式-装饰者模式

    文章目录 设计模式-装饰者模式 1. 案例引出装饰者模式 2. 装饰者模式 2.1 装饰者模式定义 2.2 装饰者模式原理 2.3 装饰者模式解决星巴克咖啡订单问题 2.4 代码实现 抽象类Drink ...

  4. [Head First设计模式]山西面馆中的设计模式——装饰者模式

    原文:[Head First设计模式]山西面馆中的设计模式--装饰者模式 引言 在山西面馆吃鸡蛋面的时候突然想起装饰者这个模式,觉得面馆这个场景跟书中的星巴兹咖啡的场景很像,边吃边思考装饰者模式.这里 ...

  5. 设计模式装饰者模式_装饰者模式如何拯救了我的一天

    设计模式装饰者模式 在工作中,我正在处理庞大的Java代码库,该代码库是由许多不同的开发人员在15年的时间里开发的. 并不是所有的事情都由书来完成,但是同时我通常无法重构遇到的每一个奇怪的事物. 尽管 ...

  6. 23种设计模式——装饰者模式

    文章目录 23种设计模式--装饰者模式 1.装饰者模式概述 2.装饰者模式的结构 3.装饰者模式的实现 4.装饰者模式的应用场景 23种设计模式--装饰者模式 1.装饰者模式概述 背景 有些人为了早上 ...

  7. 读书笔记---Head First 设计模式--- 装饰者模式

    读书笔记-Head First 设计模式- 装饰者模式 装饰者模式(Decorator Pattern) 装饰者模式--动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. ...

  8. Go 设计模式 - 装饰器模式

    装饰模式使用对象组合的方式动态改变或增加对象行为.Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式.使用匿名组合,在装饰器中不必显式定义转调原对象方法. 设计模式 装饰器模式 装饰器模式主要 ...

  9. Spring设计模式(装饰器模式)

    Spring设计模式(装饰器模式) 模式的定义: 装饰者模式定义: ​ 动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案. 模式的结构图 : 模式包含角 ...

最新文章

  1. python 因果推断_KDD 2018:微软推出用于因果推断的Python库
  2. 闲话WPF之五(XAML中的类型转换)
  3. oracle 存储过程
  4. Waymo无人卡车高调重返凤凰城,重点路测高速和主干道,但货运先机已失
  5. AIX详细查看用户/进程使用内存
  6. BZOJ5343[Ctsc2018]混合果汁——主席树+二分答案
  7. python打印四种三角形
  8. c#中ToString(yyyyMMdd) 与ToString(yyyymmdd)区别
  9. 现代信号处理——参数估计理论(估计量的性能)
  10. 安卓手机修改ip软件_为什么苹果手机不用杀毒软件?安卓表示要哭了
  11. 《数学建模与数学实验》第5版 插值与拟合 习题7.6
  12. VSCode远程控制服务器
  13. 泡泡龙游戏开发系列教程(五)
  14. FDTD_谐振腔的Q值计算(2D/3D)
  15. html表单导入图片,from 表单上传图片
  16. android svg路径动画,Android和播放SVG动画
  17. python复数计算符号_Python:基本运算、基本函数(包括复数)、Math模块、NumPy模块...
  18. 走ORACLE后门cusor_sharing的问题
  19. cornell grasp data 康奈尔大学抓取数据集 百度云
  20. 高德地图——切换路线的不同实现(驾车、公交、骑行)

热门文章

  1. 自检代码中trustmanager漏洞_Windows内核漏洞利用教程
  2. access的papersize命令_巡检命令及查看参数
  3. Unity2018.3中文更新日志速览版
  4. 在C#中对列表/数组进行碎片整理——关闭所有空白
  5. Chrome 将不再允许 https:// 页面加载 HTTP 资源
  6. SQL索引管理器——用于SQL Server和Azure上的索引维护的免费GUI工具
  7. python123平台作业答案循环结构棋盘放米_python练习集100题(1-20)
  8. python提取文本中的数字_EXCEL中提取汉字、字母、数字如此简单
  9. PHP 开发邀请功能,使用 larainvite 为 Laravel 5.3 应用添加邀请注册功能
  10. concurrentbag 删除指定元素_Python 列表,for循环,元组的使用(修改、添加、删除、排序、切片)