1. 简介

装饰器模式(Decorator
Pattern)
:允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

2. 范例:咖啡店

刚开始时,咖啡店的程序设计是:

  • 一个咖啡饮料的父类 Beverage,抽象类,店里的所有饮料都必须继承此父类
  • 不同种类的咖啡饮料都是一个类(都需要继承 Beverage类)

带来的问题:

购买咖啡饮料时,客户可以要求加入不同中类的配料,如:摩卡、奶泡…

此时的咖啡店的程序设计是:

3. 优化方案:实例变量和继承

Beverage类优化:

Beverage类中新增表示各种调料的实例变量


咖啡饮料类:

带来的问题:

  • 调料价格的改变需要修改代码
  • 新增调料需要改变Beverage类的 cost()方法

设计原则:类应该对扩展开放,对修改关闭

4. 优化方案:装饰者模式

以咖啡饮料为主体,然后在运行时以调料来装饰(decorate)咖啡饮料。比如,如果顾客想要摩卡和奶泡深培咖啡,那么,做法是:

  1. 获取一个深培咖啡(DarkRoast)对象
  2. 以摩卡(Mocha)调料对象来装饰它
  3. 以奶泡(Whip)调料对象来装饰它
  4. 调用cost()方法,并依赖委托(delegate)将调料的价格加上去

做法图解:

  1. 获取一个深培咖啡(DarkRoast)对象


2. 顾客想要摩卡(Mocha)调料,所以建立一个Mocha对象,并用它将DarkRoast对象包(wrap)起来


3. 顾客想要奶泡(Whip),所以建立一个Whip装饰者,并将它Mocha对象包起来


4. 计算总价钱,调用最外层的装饰者(Whip)的cost()方法就可以计算出总价钱。Whip的cost()方法会委托它装饰的对象,即Mocha,计算出价钱,然后再加上奶泡的价钱

3.1 代码

Beverage类:

package com.jbp.designpattern.decorate;/*** @ClassName: Beverage* @description: 咖啡饮料父类* @author: JiangBeiPing* @create: 2021-06-29 15:53* @Version: 1.0**/
public abstract class Beverage {String description = "咖啡饮料父类";public String getDescription() {return description;}public abstract double cost();
}

咖啡饮料类:

package com.jbp.designpattern.decorate;/*** @ClassName: Espresso* @description: 浓缩咖啡* @author: JiangBeiPing* @create: 2021-06-29 15:59* @Version: 1.0**/
public class Espresso extends Beverage{public Espresso() {description = "浓缩咖啡";}@Overridepublic double cost() {return 1.99;}
}
package com.jbp.designpattern.decorate;/*** @ClassName: HouseBlend* @description: 混搭咖啡* @author: JiangBeiPing* @create: 2021-06-29 16:02* @Version: 1.0**/
public class HouseBlend extends Beverage{public HouseBlend() {description = "混搭咖啡";}@Overridepublic double cost() {return 1.5;}
}

调料类:

package com.jbp.designpattern.decorate;/*** @ClassName: Condiment* @description: 调料* @author: JiangBeiPing* @create: 2021-06-29 15:55* @Version: 1.0**/
public abstract class CondimentDecorate extends Beverage {@Overridepublic abstract String getDescription();}
package com.jbp.designpattern.decorate;/*** @ClassName: Mocha* @description: 摩卡* @author: JiangBeiPing* @create: 2021-06-29 16:03* @Version: 1.0**/
public class Mocha extends CondimentDecorate{/*** 让Mocha对象能够引用一个Beverage*          用一个实例变量记录饮料,即被装饰者*          让被装饰者(饮料)被记录到实例变量中(此处做法是:把饮料作为构造器的参数,再由构造器将此饮料记录在实例变量中)*/Beverage beverage;public Mocha(Beverage beverage) {this.beverage = beverage;}@Overridepublic double cost() {// 计算带Mocha的咖啡饮料的价钱:Mocha的价钱 + 咖啡饮料的价钱return 0.5 + beverage.cost();}@Overridepublic String getDescription() {return beverage.getDescription() + ",摩卡";}
}
package com.jbp.designpattern.decorate;/*** @ClassName: Whip* @description: 调料:奶泡* @author: JiangBeiPing* @create: 2021-06-29 16:29* @Version: 1.0**/
public class Whip extends CondimentDecorate{Beverage beverage;public Whip(Beverage beverage) {this.beverage = beverage;}@Overridepublic double cost() {return 0.8 + beverage.cost();}@Overridepublic String getDescription() {return beverage.getDescription() + ",奶泡";}
}

测试:

package com.jbp.designpattern.decorate;/*** @ClassName: Test* @description:* @author: JiangBeiPing* @create: 2021-06-29 16:13* @Version: 1.0**/
public class Test {public static void main(String[] args) {Beverage espresso = new Espresso();//咖啡饮料:浓缩咖啡,价钱:1.99System.out.println("咖啡饮料:" + espresso.getDescription() + "," + "价钱:" + espresso.cost());Beverage houseBlend = new HouseBlend();// 加摩卡houseBlend = new Mocha(houseBlend);// 加奶泡houseBlend = new Whip(houseBlend);//咖啡饮料:混搭咖啡,摩卡,奶泡,价钱:2.8System.out.println("咖啡饮料:" + houseBlend.getDescription() + "," + "价钱:" + houseBlend.cost());}
}

3.2 总结

4. Java中的装饰者模式

IO流API:


《Head First 设计模式》(三):装饰者模式相关推荐

  1. 前端也要学系列:设计模式之装饰者模式

    什么是装饰者模式 今天我们来讲另外一个非常实用的设计模式:装饰者模式.这个名字听上去有些莫名其妙,不着急,我们先来记住它的一个别名:包装器模式. 我们记着这两个名字来开始今天的文章. 首先还是上< ...

  2. 【设计模式】装饰者模式 ( 概念 | 适用场景 | 优缺点 | 与继承对比 | 定义流程 | 运行机制 | 案例分析 )

    文章目录 I . 装饰者模式概念 II . 装饰者模式适用场景 III . 装饰者模式优缺点 IV . 装饰者模式与继承对比 V . 装饰者模式相关设计模式 VI . 装饰者模式四个相关类 VII . ...

  3. 设计模式学习----装饰器模式

    这两天本来是自在学习java collection Framework的Fail Fast底层机制,看到核心的部分时,突然意识到设计模式的问题,上大学到现在我还没有真正理解过设计模式的概念,于是用了大 ...

  4. C#设计模式(9)——装饰者模式(Decorator Pattern)

    一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...

  5. 设计模式之装饰者模式--钢铁侠的形成

    前言 本文主要讲述java常见设计模式之装饰者模式,文中使用通俗易懂的案例,使你更好的学习本章知识点并理解原理,做到有道无术. 一.什么是装饰者模式 装饰者模式是23种设计模式中结构型模式的一种,它的 ...

  6. 设计模式之装饰者模式(五)

    设计模式之装饰者模式(五) 前几天把创建型设计模式学习了一下,因为之前了解过,算是复习吧. 接下来进行结构型设计模式,结构型设计模式包括:适配器,桥接,外观,组合,装饰者,享元,代理 今天来学习装饰者 ...

  7. 设计模式之装饰器模式详解

    设计模式之装饰器模式详解 文章目录 设计模式之装饰器模式详解 一.什么是装饰器模式 二.装饰器模式的角色组成 三.装饰器模式通用写法示例 四.装饰器模式业务中的应用举例 五.装饰器模式优缺点 一.什么 ...

  8. 设计模式三—抽象工厂模式

    设计模式三-抽象工厂模式 一.定义 抽象工厂模式是工厂方法模式的进一步抽象.如果产品簇中只有一种产品,则退化为工厂方法模式. 二.原理图 三.代码实例 * 苹果和土豆是园丁1的杰作 * 葡萄和西红柿是 ...

  9. Java设计模式(装饰者模式-组合模式-外观模式-享元模式)

    Java设计模式Ⅳ 1.装饰者模式 1.1 装饰者模式概述 1.2 代码理解 2.组合模式 2.1 组合模式概述 2.2 代码理解 3.外观模式 3.1 外观模式概述 3.2 代码理解 4.享元模式 ...

  10. 设计模式 之 装饰者模式

    2019独角兽企业重金招聘Python工程师标准>>> 设计模式 之 装饰者模式 装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对 ...

最新文章

  1. RESTful之路由Routers
  2. Java Web学习总结(22)——使用kaptcha生成验证码
  3. pycharm 类型注释_后端开发使用pycharm的技巧
  4. golang协程介绍和理解
  5. keyloadtool_keytool:术语“keytool”无法识别为cmdlet、函数、脚本文件或可操作程序的名称...
  6. Xamarin Studio支持TypeScript开发
  7. java之包装类与BigInteger、BigDecimal
  8. MIPCache 域名升级
  9. Android studio 快速解决Gradle's dependency cache may be corrupt 和 Gradle配置 gradle-3.*-all.zip快速下载
  10. Why Helm? - 每天5分钟玩转 Docker 容器技术(160)
  11. ORA-01078: failure in processing system parameters
  12. 从零基础入门Tensorflow2.0 ----七、34 embedding rnn
  13. 【自动驾驶】MPC控制器 + 驾驶模型器
  14. 手机怎么查看连接过的wifi密码
  15. 爬虫python下载电影_Python 爬虫实战:分析豆瓣中最新电影的影评
  16. 编辑器开发(一):准备工作,百度ueditor移入项目当中
  17. Fiddler+雷电模拟器进行APP抓包
  18. 工具提取MP4中的音视频
  19. matlab的round函数是什么意思,Oracle round函数是什么意思?怎么运用?
  20. 解决双显卡无法安装Ubuntu问题(转载)

热门文章

  1. 笔试遇到的rgba转16进制,但透明度不需要加到里面
  2. Matlab画圆且坐标轴图片等比例显示
  3. java软件工程师月薪多少?
  4. 货币代码,不允许ALE通讯
  5. 图像识别并用机械手进行抓取
  6. vpx计算机论文,vpx总线
  7. VPX,CompactPCI serial 总线
  8. 附合导线坐标计算例题_闭合附合导线计算(课件例题)
  9. Win10桌面背景(壁纸)导出工具
  10. Xv6 Page Table