文章目录

  • I . 装饰者模式概念
  • II . 装饰者模式适用场景
  • III . 装饰者模式优缺点
  • IV . 装饰者模式与继承对比
  • V . 装饰者模式相关设计模式
  • VI . 装饰者模式四个相关类
  • VII . 装饰者模式实体装饰者类运行机制
  • VIII . 装饰者模式定义使用流程 ( 重点 )
  • IX . 装饰者模式 案例

I . 装饰者模式概念


装饰者模式概念 :

① 设计模式类型 : 结构性 ;

② 概念 : 不改变原有类的对象 , 动态地将额外的功能附加到该对象上 ;

③ 扩展对象功能 : 这种功能扩展方式比类继承更加灵活 ;

④ 装饰者模式 : 移除类中的被装饰功能 , 将被装饰类简化 , 区分类的核心职责 和 装饰功能 ;

II . 装饰者模式适用场景


装饰者模式适用场景 :

① 功能扩展 : 为一个类扩展功能 , 为其添加额外的职责 ; ( 强调扩展 )

② 动态添加撤销功能 : 为一个对象动态添加额外功能 , 同时这些被添加的功能还能被动态撤销 ; ( 强调动态 )

III . 装饰者模式优缺点


装饰者模式优点 :

① 扩展灵活 : 使用装饰者模式 , 比继承更加灵活 ; 使用装饰者模式扩展类功能 , 不会改变原来的类 ;

② 排列组合 : 对装饰类进行各种排列组合 , 可实现不同的扩展功能 ;

③ 开闭原则 : 装饰者模式符合开闭原则 , 被装饰的类 , 和装饰类相互独立 , 互不干扰 ;

装饰者模式缺点 :

① 程序复杂 : 需要编写更多的代码 , 生成更多的类 , 程序的复杂性增加了 ;

② 动态 / 多层 装饰 : 动态 / 多层 装饰一个类时 , 程序更复杂 ;

IV . 装饰者模式与继承对比


继承与装饰者模式对比 :

① 继承复杂 : 使用继承扩展功能 , 需要生成很多子类 , 系统复杂性增加 ;

② 继承静态 : 继承在编译时就要确定扩展的功能 , 是静态的 ;

③ 装饰者模式动态扩展 : 装饰者模式可以动态扩展功能 , 可以在代码运行时扩展功能 ;

V . 装饰者模式相关设计模式


1 . 装饰者模式与代理模式 :

① 注重点 : 装饰者模式注重动态扩展功能 ; 代理模式注重对对象访问的控制 , 代理类对用户隐藏具体细节 ;

② 实例对象的使用 : 装饰者模式将原始对象作为参数传递给装饰者类构造器 ; 代理模式中在代理类中创建实例对象 ;

2 . 装饰者模式与适配器模式 : 二者都是包装模式 ;

① 装饰者模式 : 装饰者模式中 , 装饰者和被装饰这实现相同的接口 , 或装饰者是被装饰者的子类 ;

② 适配器模式 : 适配器模式中 , 适配器和被适配的类有不同的接口 , 可能有部分接口重合 ;

VI . 装饰者模式四个相关类


装饰者模式四个相关类 :

① 抽象的 被装饰者类 : 这是核心 , 后面的三个类都需要继承该类 ;

② 实体的被装饰者类 : 定义装饰者模式时 , 用不到 , 在客户端被用户调用时 , 才初始化 ;

③ 抽象的装饰者类 : 所有装饰者类的父类 , 需要继承抽象的被装饰者类 ; ( 该类可选配 , 不是必须 )

④ 实体的装饰者类 : 继承 抽象的装饰者类 , 在该类中维护一个 抽象装饰者类对象 , 通过构造函数传入实体的被装饰者类 , 其实现的 抽象的装饰者类 方法中 , 需要调用传入的实体对象的对应方法 , 然后加入额外的操作 ;

VII . 装饰者模式实体装饰者类运行机制


实体的装饰者类运行机制 :

① 核心 : 核心是 抽象的 被装饰者类 类型 ,

② 装饰者类型 : 实体的装饰者类是 抽象的 被装饰者类 类型的 ,

③ 装饰者中维护的变量类型 : 其中维护的实例成员变量也是 抽象的 被装饰者类 类型的 ,

④ 装饰者模式运行 : 装饰者模式使用时 , 先创建一个 抽象的 被装饰者类 实例对象 , 创建一个装饰者对象 , 通过构造函数将上面的实例对象传入 , 整个装饰者模式就是为该实例对象进行扩展的 ;

⑤ 装饰可循环嵌套 : 实体的被装饰类类型是 抽象的 被装饰者类 类型的 , 其被装饰后 , 还是 抽象的 被装饰者类 类型的 , 然后还可以再次装饰 , 实体的被装饰类的动态功能的扩展 , 可以被无限装饰扩展 ;

VIII . 装饰者模式定义使用流程 ( 重点 )


1 . 定义抽象被装饰者 : 定义 抽象的 被装饰者类 , 将其要扩展的方法定义成抽象方法 ;

2 . 定义 ( 抽象的 ) 装饰者类 :

① 继承 抽象的 被装饰者类 : 装饰者类 继承 抽象的 被装饰者类 ;

② 维护 抽象的 被装饰者类 成员 : 在该类中维护一个 抽象的 被装饰者类 对象 , 该对象通过构造函数传入 ;

③ 实现抽象方法委托 : 装饰者类中的抽象方法 , 需要委托给类中维护的 抽象的 被装饰者类 对象 , 在实现的该抽象方法中 , 调用上面对象的对应方法 , 然后加上要扩展的代码 , 这些扩展的代码 , 就是装饰者模式位该对象动态扩展的功能 ;

3 . 定义实体对象 : 该对象是 抽象的 被装饰者类 类型的 , 是具体的实体功能 , 要实现实际的大块代码逻辑 , 所有的操作 , 装饰 , 都基于该实体对象类 ;

上面的装饰者类 只关心被装饰的方法 , 不定义其它内容 ;

4 . 使用装饰者模式 :

① 创建 抽象的 被装饰者类 实体对象 ;

② 装饰实体对象类 : 创建 抽象的 被装饰者类 类型的装饰者类 , 在构造函数中 , 传入 ① 中创建的 抽象的 被装饰者类 类型的 实体对象 ;

③ 再次装饰实体对象类 : 再次创建 抽象的 被装饰者类 类型的装饰者类 , 在构造函数中 , 传入 ② 中创建的 抽象的 被装饰者类 类型的 装饰者实体对象 , 这样就实现了二次装饰 ;

使用的对象类型是 抽象的 被装饰者类 , 被装饰的对象 , 传入装饰者类 , 相当于包装了一层 , 其对象类型还是 抽象的 被装饰者类 , 这个包装装饰可以循环嵌套 ;

IX . 装饰者模式 案例


1 . 案例需求 :

① 实体类对象 : 刚入学的学生 , 默认学习大学公共课 ,

② 装饰类对象 : 如果是计算机专业的学生 , 还要继续学习计算机专业课程 ,

③ 装饰类对象 : 如果是音乐专业的学生 , 需要继续学习音乐专业课程 ,

④ 二次装饰类对象 : 如果是先学习计算机 , 然后专修音乐 , 那么需要先学习计算机专业课程 , 然后学习音乐专业课程 ;

2 . 抽象的 被装饰者类 : 抽象的学生类 , 后面的计算机专业学生装饰者 , 音乐专业学生装饰者都继承该类 ;

package kim.hsl.design.decorator;/*** 装饰者* 抽象的装饰者* 该类也继承 被装饰者 的抽象类*/
public abstract class AbstractDecorator extends AbstractStudent {//声明抽象的被装饰者, 通过构造器将其类型 ( 或子类类型 ) 对象传入 , 注入实体类private AbstractStudent abstractStudent;public AbstractDecorator(AbstractStudent abstractStudent) {this.abstractStudent = abstractStudent;}/*调用实现的两个 抽象装饰者 方法实际上委托给了注入的 抽象装饰者 类型的对象执行的抽象装饰者 类型的对象是其子类对象*/@Overrideprotected String studyCourses() {return this.abstractStudent.studyCourses();}
}

3 . 刚入学的学生类 : 这是最普通的实体 , 是被装饰的实体类 , 一切装饰都是围绕着该实体来的 ;

package kim.hsl.design.decorator;/*** 被装饰对象* 确定的实体类*/
public class Student extends AbstractStudent {@Overrideprotected String studyCourses() {return "学习大学公共课";}
}

4 . 抽象的被装饰者类 : 该类也是 抽象的被装饰者 类 AbstractStudent 的子类 , 该类中维护了 AbstractStudent 类型的成员变量 , 通过构造函数初始化 ; 其 studyCourses 方法需要委托给 abstractStudent 成员变量的 abstractStudent 方法 ;

package kim.hsl.design.decorator;/*** 装饰者* 抽象的装饰者* 该类也继承 被装饰者 的抽象类*/
public abstract class AbstractDecorator extends AbstractStudent {//声明抽象的被装饰者, 通过构造器将其类型 ( 或子类类型 ) 对象传入 , 注入实体类private AbstractStudent abstractStudent;public AbstractDecorator(AbstractStudent abstractStudent) {this.abstractStudent = abstractStudent;}/*调用实现的两个 抽象装饰者 方法实际上委托给了注入的 抽象装饰者 类型的对象执行的抽象装饰者 类型的对象是其子类对象*/@Overrideprotected String studyCourses() {return this.abstractStudent.studyCourses();}
}

5 . 计算机专业学生装饰者类 : 传入 AbstractStudent 成员变量 , studyCourses 方法中 , 在学习公共课基础上 ( 委托成员变量 ) , 还学习 计算机专业课程 ;

package kim.hsl.design.decorator;/*** 实体装饰者类* 必须实现其带参数的构造器*/
public class ComputerStudentDecorator extends AbstractDecorator {public ComputerStudentDecorator(AbstractStudent abstractStudent) {super(abstractStudent);}@Overrideprotected String studyCourses() {return super.studyCourses() + " , 学习计算机专业课程";}
}

6 . 音乐专业学生装饰者类 :

package kim.hsl.design.decorator;public class MusicStudentDecorator extends AbstractDecorator {public MusicStudentDecorator(AbstractStudent abstractStudent) {super(abstractStudent);}@Overrideprotected String studyCourses() {return super.studyCourses() + " , 学习音乐专业课程";}
}

7 . 测试装饰者模式 : 其中测试了没有装饰的实体类 , 将其装饰成计算机专业学生 , 将其装饰成音乐专业学生 , 将其装饰成计算机转音乐专业的学生 ;

package kim.hsl.design.decorator;public class Main {public static void main(String[] args) {//刚入学的学生Student student = new Student();System.out.println(student.studyCourses());//大二学习计算机专业课程AbstractStudent computerStudent = new ComputerStudentDecorator(student);System.out.println(computerStudent.studyCourses());//大二学习音乐专业课程AbstractStudent musicStudent = new MusicStudentDecorator(student);System.out.println(musicStudent.studyCourses());//先学计算机 , 专修音乐的学生AbstractStudent computerMusicStudent = new ComputerStudentDecorator(computerStudent);System.out.println(computerMusicStudent.studyCourses());}
}

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

  1. 【设计模式】外观模式 ( 概念 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 I . 外观模式概念 II . 外观模式 适用场景 III . 外观模式 优缺点 IV . 外观模式与其它设计模式的联系与区别 V . 外观模式 代码示例 I . 外观模式概念 1 . 外观 ...

  2. 【设计模式】策略模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.策略模式简介 二.策略模式适用场景 三.策略模式优缺点 四.策略模式与其它设计模式 五.策略模式代码示例 1.促销策略接口 2.满减促销策略 3.返现促销策略 4.空促销策略 5.促销策 ...

  3. 【设计模式】模板方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.模板方法模式简介 二.模板方法模式适用场景 三.模板方法模式优缺点 四.模板方法扩展 五.模板方法模式相关设计模式 六.模板方法模式代码示例 1.模板方法抽象类 2.模板方法实现类 1 ...

  4. 【设计模式】状态模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.状态模式简介 二.状态模式适用场景 三.状态模式优缺点 四.状态模式相关设计模式 五.状态模式代码示例 1.状态类父类 2.播放状态类 3.暂停状态类 4.快进状态类 5.停止状态类 6 ...

  5. 【设计模式】访问者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.访问者模式简介 二.访问者模式 适用场景 三.访问者模式 优缺点 四.访问者模式 与 迭代器模式 五.代码示例 1.Game 父类 ( 被访问者 ) 2.VipGame 收费游戏 ( 被 ...

  6. 【设计模式】桥接模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.桥接模式简介 二.桥接模式适用场景 三.桥接模式优缺点 四.桥接模式相关设计模式 五.桥接模式代码示例 1.视频格式抽象 2.FLV 视频格式实现 3.MP4 视频格式实现 4.系统平台 ...

  7. 【设计模式】解释器模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.解释器模式简介 二.解释器模式适用场景 三.解释器模式优缺点 四.解释器模式与适配器模式 五.解释器模式代码示例 1.解释器接口 2.加法解释器 3.乘法解释器 4.整型解释器 5.语法 ...

  8. 【设计模式】建造者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.建造者模式简介 二.建造者模式适用场景 三.建造者模式优缺点 四.建造者模式与工厂模式 五.建造者模式代码示例 1.学生类 2.建造者抽象类 3.建造者实现类 4.教师类 ( 非必须 ) ...

  9. 【设计模式】组合模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.组合模式简介 二.组合模式适用场景 三.组合模式优缺点 四.组合模式和访问者模式 五.组合模式代码示例 1.书籍和目录的抽象父类 2.书籍类 3.目录类 4.测试类 一.组合模式简介 组 ...

最新文章

  1. [算法] [常微分方程] [欧拉法 改进欧拉法 经典R-K算法]
  2. 输出程序运行的时间(精确到微秒)
  3. 妙用QTP F1帮助功能
  4. 成都黑帽门图片大全_2020成都第一波出行/便民/打卡免费大全
  5. iOS js oc相互调用(JavaScriptCore)(二)
  6. 【Android 插件化】VAHunt 检测插件化引擎的具体细节
  7. 编译原理【实验1——扫描器的设计与实现】
  8. 计算机VB整除,【原创】VB中的整除运算和转换函数
  9. Tomcat应用中post方式传参数长度限制
  10. C++中两个常用的控制语句格式的函数(width和precision函数)
  11. 【转载】Android 关于arm64-v8a、armeabi-v7a、armeabi、x86下的so文件兼容问题
  12. Cisco3550三层交换机vlan间路由配置实例
  13. springAOP之代理
  14. 查找文章中出现频率最高的单词
  15. Drupal 7.17 发布,专业的 CMS 内容管理系统
  16. matlab mosek安装
  17. 计算机如何认硬盘,电脑怎样识别大容量的硬盘?
  18. 国产化操作系统安装OpenJDK Icedtea插件
  19. 【Linux】Infiniband 驱动安装---(HCA光钎)---mlnx
  20. html动画爱心制作代码,CSS心形加载的动画源码的实现

热门文章

  1. AppDomain,应用程序域
  2. 好久没写博客了,改天要把原博客资料整理下,弄个链接什么
  3. [BZOJ4553][TJOI2016HEOI2016]序列(CDQ分治)
  4. avalon $computed不起作用?
  5. 网易笔试——混合颜料
  6. iOS学习笔记---oc语言第八天
  7. Linq 入门系列 [OfType,ToArray,ToList,ToDictionary]
  8. [导入]web2.0中流行的设计元素:颜色
  9. 关于可扩展的web架构设计的探索-框架结构的描述文件
  10. shell脚本[] [[]] -n -z 的含义解析