装饰器模式

装饰器模式(Decorator Patter),也称为包装模式(Wrapper Pattern)是指在不改变原有对象的基础之上,将功能附加在对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。

装饰器模式的核心是功能扩展。使用装饰器可以透明且动态地扩展类的功能。

下面是通用的UML类图:

生活中的应用场景

看完上面的概念以及类图可能比较抽象,接下来我会举一个生活中的场景,来通俗易懂的讲解装饰器模式。

我们在早上上班途中,往往会在公司门口买一个手抓饼,然后带到工位上慢慢吃,相信很多小伙伴有过类似的经历。那么一个手抓饼什么都不加就是五块钱,我们把这个叫做标配,当然也可以按照你的喜好做一些定制化的需求,加里脊,加生菜,加培根等等,全凭个人的喜好来,这个过程就是一个装饰器模式。

下面我们用代码还原一下码农的生活。首先创建一个手抓饼的抽象Pancake类:

/*** @author jackxu*/
public abstract class Pancake {protected abstract String getMsg();protected abstract int getPrice();}

创建一个基本的手抓饼类BasePancake,我们把这个叫做标配,就是什么都不加的五块钱一个

/*** @author jackxu*/
public class BasePancake extends Pancake {@Overrideprotected String getMsg() {return "标配手抓饼";}@Overridepublic int getPrice() {return 5;}}

然后再创建一个扩展手抓饼的抽象装饰器PancakeDecorator类:

/*** @author jackxu*/
public class PancakeDecorator extends Pancake {private Pancake pancake;public PancakeDecorator(Pancake pancake) {this.pancake = pancake;}@Overrideprotected String getMsg() {return this.pancake.getMsg();}@Overridepublic int getPrice() {return this.pancake.getPrice();}}

创建一个继承自抽象装饰器类的生菜装饰器LettuceDecorator类:

/*** @author jackxu*/
public class LettuceDecorator extends PancakeDecorator {public LettuceDecorator(Pancake pancake) {super(pancake);}@Overrideprotected String getMsg() {return super.getMsg() + "+1片生菜";}@Overridepublic int getPrice() {return super.getPrice() + 1;}}

同理创建一个鸡蛋装饰器EggDecorator类:

/*** @author jackxu*/
public class EggDecorator extends PancakeDecorator {public EggDecorator(Pancake pancake) {super(pancake);}@Overrideprotected String getMsg() {return super.getMsg() + "+1个鸡蛋";}@Overridepublic int getPrice() {return super.getPrice() + 1;}}

好,现在所有的类都已经写完了,让我们写个测试用例来测试一下:

/*** @author xhj* @date 2021/2/23 16:45*/
public class Test {public static void main(String[] args) {//A同学买了一个标配Pancake pancake = new BasePancake();System.out.println("A同学买了一个" + pancake.getMsg() + ",总价是" + pancake.getPrice() + "元");//B同学买了加鸡蛋的手抓饼Pancake pancakeWithEgg = new EggDecorator(pancake);System.out.println("B同学买了一个" + pancakeWithEgg.getMsg() + ",总价是" + pancakeWithEgg.getPrice() + "元");//C同学买了加生菜的手抓饼Pancake pancakeWithLettuce = new LettuceDecorator(pancake);System.out.println("C同学买了一个" + pancakeWithLettuce.getMsg() + ",总价是" + pancakeWithLettuce.getPrice() + "元");//D同学买了加鸡蛋加生菜的手抓饼Pancake pancakeWithEggAndLettuce = new LettuceDecorator(pancakeWithEgg);System.out.println("D同学买了一个" + pancakeWithEggAndLettuce.getMsg() + ",总价是" + pancakeWithEggAndLettuce.getPrice() + "元");}}

运行结果:

怎样,与我们预期希望看到的结果相符吧,我们用代码还原了现实生活中的一个场景。标配还是那个标配,对于别的需求,我们可以通过层层包装、装饰来实现很多的排列组合,而不是通过继承的方式,为每一种情况都生成一个类,那这样就会产生很多的类,这就是装饰器巧妙、灵活的地方。

最后让我们看下这几个类的UML类图:

和上面通用的类图长的一样吧,这里的PancakeDecorator抽象装饰器是非必需的,如果装饰器多的话我们可以抽象一个出来,如果装饰器单一的话,就可以省略该类,直接继承Pancake实现一个具体装饰器即可。

源码中的应用场景

当我在学习mybatis里面的一级缓存和二级缓存的时候,我看它的源码,发现在cache包下面有一个熟悉的单词,那就是decorators,这个就是装饰的意思,我大胆的猜测它用的就是装饰器模式。

查看了一下引用,发现一段似曾相识的代码,原来decorators包下的每一个类都是装饰类,这里面将cache层层的包装,达到对缓存作用增强的功能。

具体增强的功能如下:

装饰器模式的优缺点

优点:

  • 装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。
  • 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。
  • 装饰器完全遵守开闭原则。
    缺点:
  • 会出现更多的代码,更多的类,增加程序复杂性。
  • 动态装饰时,多层装饰会更复杂。

源码

https://github.com/xuhaoj/pattern-demo ,其他设计模式的例子也在该项目中,谢谢大家的观看。

手抓饼加生菜加鸡蛋的装饰器模式相关推荐

  1. 通过装饰器模式为 RoundedBitmapDrawable 加边框

    1. 为什么要给 RoundedBitmapDrawable 加边框? 在我们平时生活中,大多数的 App 不光是圆角头像,有很多 App 在圆角头像上还加了一个边框,如: 今天我们就在 <看完 ...

  2. python中的装饰器、装饰器模式_python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

  3. python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

  4. 【设计模式(九)】结构型模式之装饰器模式

    个人学习笔记分享,当前能力有限,请勿贬低,菜鸟互学,大佬绕道 如有勘误,欢迎指出和讨论,本文后期也会进行修正和补充 前言 中秋刚过没多久,虽然我这种粗人对月饼无感,但是公司发的肯定得收的嘛 拿回家当零 ...

  5. 【源码分析设计模式 5】Java I/O系统中的装饰器模式

    一.基本介绍 动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 二.装饰器模式的结构 1.Component,抽象构件 Component是一个接口或者抽象类,是定义我们 ...

  6. 设计模式之装饰器模式(C++实现)

    更多设计模式参看: 设计模式之模式概述(模式汇总)(C++实现) 文章目录 介绍 意图: 解决问题: 实现概述: 要点: 应用场景: 优点: 缺点: 模式结构 角色 类图 代码示例 GitHub Co ...

  7. 设计模式之门面模式与装饰器模式详解和应用

    目录 1 门面模式定义 1.1 门面模式的应用场景 1.2 门面模式的通用写法 1.3 门面模式业务场景实例 1.4 门面模式在源码中的应用 1.5 门面模式的优缺点 2 装饰器模式 2.1 装饰器模 ...

  8. java设计模式之装饰器模式

    一.装饰器模式简介 装饰器模式可以动态给一个对象添加一些额外的职责,同时又不改变其结构.就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.这种模式创建了一个装饰 ...

  9. 装饰器模式与java.io包

    为什么80%的码农都做不了架构师?>>>    Decorator设计模式是典型的结构型模式(在GOF的那本模式的Bible中将模式分为:1.创建型模式:2.结构型模式:3.行为模式 ...

最新文章

  1. Linux下查看系统信息
  2. (JAVA学习笔记) 如何计算2*8效率高(面试题)—— 左移和右移问题。
  3. wxwidget编译安装_wxWidgets编译安装方法 | 学步园
  4. PCL中有哪些可用的PointT类型(4)
  5. AOP(面向切面编程)大概了解一下
  6. elasticsearch 6.x (四) 单一文档 API 介绍和使用 index和get API
  7. java channel源码_Netty 4.0 源码分析(三):Channel和ChannelPipeline
  8. 制作CentOS 5.9自动安装光盘iso镜像
  9. 傅里叶变换原理讲解及python手动实现
  10. spark中的广播变量与累加器
  11. TwinCAT软件部分参数介绍
  12. 计算机考研408每日一题 day162
  13. B站视频封面图片获取_CodingPark编程公园
  14. 电子科大辅助挂课、秒挂(付费)
  15. 基于opencv的图像阴影消除车辆变道检测
  16. 【高德地图进阶】--- 带图片的点(3)
  17. 基于Ubuntu9.10 雨林木风Linux Y1.5发布
  18. 翻译:SMPL-X模型与SMPLify-X方法
  19. 【系统架构师】软件架构设计——2需求与质量属性
  20. 小强升职记思维导图_《小强升职记》思维导图与总结

热门文章

  1. 老板以为最不可能离职的员工为什么往往会提出离职?
  2. hadoop启动就出现 WARN util.NativeCodeLoader:... using builtin的解决方法
  3. H5 CSS适配手机刘海屏高度
  4. windows下如何用python控制打印机打印_在windows上使用python设置打印机权限
  5. 21年抓取抖音小姐姐最新版教程!最关键的是无水印下载。这还学不会?
  6. 华为mate40pro+参数配置
  7. 英语听力练习的基本法则
  8. Java:创建方法求两个数的最大值max2,然后再写一个求三个数的最大值max3
  9. 你就像烟火的美丽,那么美丽
  10. 猫和老鼠手游怎么才能快速上分?目前胜率已经超过90%