点击上方蓝色“方志朋”,选择“设为星标”

回复“666”获取独家整理的学习资料!

作者:双子孤狼

blog.csdn.net/zwx900102/article/details/107740212

阅读目录

  • 什么是装饰者模式

  • 普通示例

  • 装饰者模式示例

  • 类图关系

  • 装饰者模式使用场景

  • 装饰者模式优点

  • 装饰者模式缺点

什么是装饰者模式

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

装饰者模式在生活中也有很多形象的例子,比如说给蛋糕加上一些水果,给披萨加上榴莲,或者说给烧饼加上鸡蛋火腿之类等等。

下面我们就以给蛋糕加上水果为例来看看如果不用装饰者模式要怎么实现,如果使用装饰者模式又要怎么实现,对比之后就知道装饰者模式的优势了。

普通示例

新建一个普通的蛋糕类:

package com.zwx.design.pattern.decorator.common;import java.math.BigDecimal;public class Cake {public String getCakeMsg(){return "我是一个8英寸的普通蛋糕";}public BigDecimal getPrice(){return new BigDecimal("68");}
}

这时候,我们需要给蛋糕加点芒果,那可以再新建一个类去继承普通Cake类,然后重写其中的方法:

package com.zwx.design.pattern.decorator.common;import java.math.BigDecimal;public class CakeAddMango extends Cake {@Overridepublic String getCakeMsg() {return super.getCakeMsg() + "+1个芒果";}@Overridepublic BigDecimal getPrice() {return super.getPrice().add(new BigDecimal("10"));}
}

这时候,如果不仅仅加芒果,还要再加点葡萄,那么可以再写一个类,继承CakeAddMango,然后重写其中的方法。

package com.zwx.design.pattern.decorator.common;import java.math.BigDecimal;public class CakeAddMangoAndGrape extends CakeAddMango {@Overridepublic String getCakeMsg() {return super.getCakeMsg() + "+1个葡萄";}@Overridepublic BigDecimal getPrice() {return super.getPrice().add(new BigDecimal("5"));}
}

写个测试类测一下:

package com.zwx.design.pattern.decorator.common;public class TestCake {public static void main(String[] args) {//普通蛋糕Cake cake = new Cake();System.out.println(cake.getCakeMsg() + ",价格:" + cake.getPrice());//加芒果蛋糕CakeAddMango cakeAddMango = new CakeAddMango();System.out.println(cakeAddMango.getCakeMsg() + ",价格:" + cakeAddMango.getPrice());//加芒果和葡萄蛋糕CakeAddMangoAndGrape cakeAddMangoAndGrape = new CakeAddMangoAndGrape();System.out.println(cakeAddMangoAndGrape.getCakeMsg() + ",价格:" + cakeAddMangoAndGrape.getPrice());}
}

输出如下结果:

我是一个8英寸的普通蛋糕,价格:68
我是一个8英寸的普通蛋糕+1个芒果,价格:78
我是一个8英寸的普通蛋糕+1个芒果+1个葡萄,价格:83

看起来挺好的,能实现,但是假如我们加2个芒果呢?或者是我要加2个普通呢,或者说芒果和葡萄要组合,数量不一定,那利用现有的类是无法实现的,只能不断加类去重写,如果业务变更频繁,修改起来会是致命的。

正因为普通的实现方法有这种缺陷,才有了装饰者模式,接下来我们来看看同一个需求利用装饰者模式是怎么实现的吧。

往期面试题:001期~180期汇总

装饰者模式示例

1、新建一个蛋糕的抽象类:

package com.zwx.design.pattern.decorator;import java.math.BigDecimal;public abstract class Cake {public abstract String getCakeMsg();public abstract BigDecimal getPrice();
}

2、然后新建一个普通蛋糕的类:

package com.zwx.design.pattern.decorator;import java.math.BigDecimal;public class BaseCake extends Cake {@Overridepublic String getCakeMsg() {return "我是一个8英寸的普通蛋糕";}@Overridepublic BigDecimal getPrice() {return new BigDecimal("68");}
}

3、新建一个蛋糕的装饰器类,内部持有蛋糕Cake对象,这个就是扩展的关键:

package com.zwx.design.pattern.decorator;import java.math.BigDecimal;public abstract class CakeDecorator extends Cake{private Cake cake;public CakeDecorator(Cake cake) {this.cake = cake;}@Overridepublic String getCakeMsg() {return this.cake.getCakeMsg();}@Overridepublic BigDecimal getPrice() {return this.cake.getPrice();}
}

4、新建一个芒果蛋糕的装饰器类继承CakeDecorator类:

package com.zwx.design.pattern.decorator;import java.math.BigDecimal;public class CakeAddGrapeDecorator extends CakeDecorator {public CakeAddGrapeDecorator(Cake cake) {super(cake);}@Overridepublic String getCakeMsg() {return super.getCakeMsg() + "+1个葡萄";}@Overridepublic BigDecimal getPrice() {return super.getPrice().add(new BigDecimal("5"));}
}

5、新建一个葡萄的装饰器类继承CakeDecorator类:

package com.zwx.design.pattern.decorator;import java.math.BigDecimal;public class CakeAddMangoDecorator extends CakeDecorator {public CakeAddMangoDecorator(Cake cake) {super(cake);}@Overridepublic String getCakeMsg() {return super.getCakeMsg() + "+1个芒果";}@Overridepublic BigDecimal getPrice() {return super.getPrice().add(new BigDecimal("10"));}
}

6、最后写一个测试类测试一下:

package com.zwx.design.pattern.decorator;public class TestCakeDecorator {public static void main(String[] args) {Cake cake = null;//普通蛋糕cake = new BaseCake();System.out.println(cake.getCakeMsg() + ",价格:" + cake.getPrice());//加一个芒果cake = new CakeAddMangoDecorator(cake);System.out.println(cake.getCakeMsg() + ",价格:" + cake.getPrice());//加一个葡萄cake = new CakeAddGrapeDecorator(cake);System.out.println(cake.getCakeMsg() + ",价格:" + cake.getPrice());//再加一个芒果cake = new CakeAddMangoDecorator(cake);System.out.println(cake.getCakeMsg() + ",价格:" + cake.getPrice());}
}

输出结果为:

我是一个8英寸的普通蛋糕,价格:68
我是一个8英寸的普通蛋糕+1个芒果,价格:78
我是一个8英寸的普通蛋糕+1个芒果+1个葡萄,价格:83
我是一个8英寸的普通蛋糕+1个芒果+1个葡萄+1个芒果,价格:93

我们可以看到,使用装饰者模式之后,扩展之前的功能变得极为方便,可以根据现有的装饰器进行任意组合。

类图关系

看一下类图,首先是一个基础抽象类定义了基本方法,然后是基础实现和基础装饰器继承并重写抽象类中的方法:

装饰者模式使用场景

  • 1、用于扩展一个类的功能或给一个类添加附加职责。

  • 2、动态的给一个对象添加功能,这些功能可以再动态的撤销。

注:MyBatis中的二级缓存就是用了装饰者模式来进行动态扩展,感兴趣的可以去了解下。

往期面试题:001期~180期汇总

装饰者模式优点

  • 1、装饰者是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象 扩展功能,即插即用。

  • 2、通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。

  • 3、装饰者完全遵守开闭原则。

装饰者模式缺点

  • 1、会出现更多的代码,更多的类,增加程序复杂性。

  • 2、动态装饰以及多层装饰时会更加复杂。

热门内容:
  • 第 3 次读 Effective Java,这 58 个技巧最值!

  • 10大黑客专用的 Linux 操作系统,每个都很酷!

  • Spring官方都推荐使用的@Transactional事务,为啥我不建议使用!

  • Java生鲜电商平台-监控模块的设计与架构

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡

如何利用装饰者模式在不改变原有对象的基础上扩展功能相关推荐

  1. 3年工作必备 装饰器模式

    故事 古话说的好:人靠衣裳马靠鞍.下面先带大家来熟悉这句话的背景: 人靠衣装马靠鞍,狗配铃铛跑的欢出自沈自晋<望湖亭记>第十出:"虽然如此,佛靠金装,人靠衣装,打扮也是很要紧的. ...

  2. 设计模式系列:搞懂装饰器模式,增加自身技能

    装饰器模式的定义:指在不改变原有对象的基础上,动态地给该对象增加一些额外的功能的模式,属于对象结构型模式. 装饰器模式的核心在于类的扩展,通过装饰器模式可以透明且动态的扩展类的功能. 装饰器模式的结构 ...

  3. java模式之装饰器模式

    定义: 装饰器模式也叫作包装器模式,只在不改变原有对象的基础上,动态的给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活,属于结构型设计模式 装饰器模式提供了比继承更有弹性的 ...

  4. 装饰者模式——NWU_LK

    目录 简介 案例描述及实现 案例描述 实现 JAVA中的装饰者模式实现 简介 装饰者模式又称包装模式,是指不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的替代方案.属于结构型设计模式 ...

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

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

  6. JavaScript设计模式(三):结构型设计模式-外观模式、适配器模式、代理模式、装饰者模式、桥接模式、组合模式、享元模式

    JavaScript设计模式 - 结构型设计模式 套餐服务-外观模式 外观模式(Facade) 水管弯弯-适配器模式 适配器模式(Adapter) 适配异类框架 参数适配 牛郎织女-代理模式 代理模式 ...

  7. 设计模式 -结构型模式_ 装饰者模式Decorator Pattern 在开源软件中的应用

    文章目录 定义 结构图 需求 装饰者模式 装饰者模式在MyBatis中的应用 小结 定义 装饰模式 Decorator : 在不改变原有功能的基础上, 动态的给一个对象添加一些额外的职责 ,非常符合开 ...

  8. 装饰者模式的应用场景

    装饰者模式(Decorator Pattern)是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式.装饰者模式在我们生活中应用也比 ...

  9. 装饰器模式(Decorator Pattern)

    23种设计模式完整教程 介绍 装饰者模式(Decorator Pattern)是指在不改变原有对象的基础之上,将功能附加到对 象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式 ...

最新文章

  1. 医疗器械软件网络安全法规和标准概述(附所有标准)
  2. linux实现自己的write函数,Linux 内核源码阅读 - write 系统调用的实现
  3. 深入浅出Shell编程: Shell 变量【ZT】
  4. 拉普拉斯算子属于卷积方法吗_2020 年 GNN 开卷有益与再谈图卷积
  5. python怎么读取csv文件-python怎么读取csv文件
  6. Tarjan点的双联通(寻找割点)
  7. 没有做数据备份 网站随时毁于一旦
  8. 博文视点经典新书样章下载
  9. office2007过期后没有输入序列号对话框的激活方法
  10. JS中编码的三种方法
  11. Windows API笔记(六)内存映射文件
  12. UI app界面的尺寸规范
  13. Qt编写水波进度条控件
  14. Proximal Algorithms 1 介绍
  15. MiKTeX安装及添加到环境变量
  16. 数据治理的成功要素2:数据架构设计
  17. 笔记 | 笨方法学Python
  18. 笔记本电脑锁屏密码能输入,但解锁后键盘不好用
  19. go 源码工具解析-英文单复数变化 Inflection
  20. 阿里达摩院春招 Research Intern 招聘

热门文章

  1. HDU 2561 第二小整数
  2. Linux 工具进阶
  3. BGA封装芯片手工焊接攻略
  4. 通过 cygwin64 自己编译对应的 Tera Term cyglaunch.exe
  5. ubuntu下安装redis
  6. 利用OWC创建图表的完美解决方案
  7. Numpy入门教程:02. 索引、切片与迭代
  8. 【怎样写代码】向现有类型“添加”方法 -- 扩展方法(二):扩展方法的实现与调用
  9. 【建模必备】遗传算法的基本原理与步骤(选择)
  10. Modeling System Behavior with Use Case(3)