当前位置: 首页 > news >正文

秒懂设计模式--学习笔记(9)【结构型-装饰器模式】

目录

      • 8、装饰器模式
          • 8.1 装饰器模式(Decorator)
          • 8.2 装修(举例)
          • 8.3 化妆(示例)
          • 8.4 化妆品的多样化
          • 8.5 装饰器
          • 8.6 自由嵌套
          • 8.7 装饰器模式的各角色定义
          • 8.8 装饰器模式

8、装饰器模式

8.1 装饰器模式(Decorator)
  • 能够在运行时动态地为原始对象增加一些额外的功能
  • 装饰器非常类似于“继承”,它们都是为了增强原始对象的功能,区别在于方式的不同
    • 后者是在编译时(compile-time)静态地通过对原始类的继承完成
    • 前者则是在程序运行时(run-time)通过对原始对象动态地“包装”完成,是对类实例(对象)“装饰”的结果
  • 测试类结构
    装饰器测试类结构
8.2 装修(举例)
  • 不改变其原始结构的前提下使客体功能得到扩展、增强
  • 以室内装潢为例
    • 装修风格多种多样
    • 朴素的毛坯房能给业主留有更大的装修选择空间,以根据自己的喜好进行二次加工
    • 成品一定是由半成品加工而成的
    • 灵活多变的装饰才会带来更多的可能,因此装饰器模式应运而生
8.3 化妆(示例)
  • 首先对于任何妆容展示者必然对应一个标准的展示行为show()
  • 我们将它抽象出来定义为接口Showable
  • Showable这个标准行为需要人去实现,定义女生类,素颜展示
    • 如果客户端直接调用show()方法,就会出现素面朝天的结果
    	package decorator;/*** 可展示者**/public interface Showable {/*** 标准展示行为*/public void show();}
    
    • 化妆品我们在这里称为“装饰器”: 化妆品装饰器类Decorator
    	package decorator.base;import decorator.Showable;/*** 化妆品装饰器类**/public class Decorator implements Showable {/***被装饰的展示者*/Showable showable;/*** 构造时注入被装饰者* @param showable*/public Decorator(Showable showable) {this.showable = showable;}@Overridepublic void show() {//化妆品粉饰开始System.out.print("粉饰【");//被装饰者的原生展示方法showable.show();//粉饰结束System.out.print("】");}}
    
    • 装饰器实现类
    	package decorator.entity;import decorator.Showable;/*** 装饰器实现类**/public class Girl implements Showable {@Overridepublic void show() {System.out.print("女生的素颜");}}
    
    • 测试类
    	package decorator.base;import decorator.entity.Girl;		/*** 客户端测试类**/public class Client {public static void main(String[] args) {//用装饰器装饰后后再展示new Decorator(new Girl()).show();}}
    
8.4 化妆品的多样化
  • 化妆品的多样性决定了装饰器应该是多态化的
    • 单个装饰器应该只负责自己的化妆功效
    • 把化妆品按功能分类才能让用户更加灵活地自由搭配,用哪个或不用哪个由用户自己决定,而不是把所有功能都固化在同一个装饰器里
    • 如果让所有化妆品类都实现Showable接口,每个化妆品类里都要引用这个被装饰者,这显然会导致代码冗余。
    • Showable接口是能够满足多态化需求的,但它只是对行为接口的一种规范,极度的抽象并不具备对代码继承的功能
  • 化妆品的多态化还需要接口与抽象类的搭配使用才能两全其美,装饰器类的抽象化势在必行
    • 我们将化妆品装饰器类修改为装饰器抽象类,这主要是为了不允许用户直接实例化此类
    • 调用了被装饰者的show()方法,而不再做任何装饰操作
    • 至于具体如何装饰则属于其子类的某个化妆品类的操作范畴了
    • 抽象装饰器DecoratorAbstract
    	package decorator.ab;import decorator.Showable;/*** 化妆品装饰器类: 抽象类**/public abstract class DecoratorAbstract implements Showable {protected Showable showable;public DecoratorAbstract(Showable showable) {this.showable = showable;}@Overridepublic void show() {// 直接调用不加任何装饰showable.show();}}
    • 实现类
      • 粉底类FoundationMakeup、口红类Lipstick
      package decorator.ab;
      import decorator.Showable;
      /*** 粉底类**/
      public class FoundationMakeup extends DecoratorAbstract {/*** 调用抽象父类的构造注入* @param showable*/public FoundationMakeup(Showable showable) {super(showable);}@Overridepublic void show() {System.out.print("打粉底【");showable.show();System.out.print("】");}
      }
      
      package decorator.ab;import decorator.Showable;/*** 口红类**/
      public class Lipstick extends DecoratorAbstract {public Lipstick(Showable showable) {super(showable);}@Overridepublic void show() {System.out.print("涂口红【");showable.show();System.out.print("】");}
      }
      
      • 不用去实现Showable接口了,而是继承了装饰器抽象类,如此父类中对被装饰者的定义得以继承
      • 重写show()方法, 加上自己特有的操作
    • 客户端类Client
      • 涂口红【打粉底【女生的脸庞】】
      • 需要注意的是一系列构造产生的顺序
 package decorator.ab;import decorator.entity.Girl;
import decorator.Showable;import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.zip.ZipInputStream;/*** 客户端测试类**/
public class Client {public static void main(String[] args) throws FileNotFoundException {test1();test2();}private static void test1() {Girl girl = new Girl();/*** 上粉底*/Showable foundationMakeup = new FoundationMakeup(girl);/*** 涂口红*/Showable medeupGirl = new Lipstick(foundationMakeup);medeupGirl.show();}private static void test2() throws FileNotFoundException {// 1.首先以文件file初始化File file = new File("/压缩包.zip");// 4.最外层再用压缩包输入流ZipInputStream进行最终装饰,使文件输入流具备Zip格式文件的功能ZipInputStream zipInputStream = new ZipInputStream(// 3.外层用缓冲输入流BufferedInputStream进行装饰,使文件输入流具备内存缓冲的功能new BufferedInputStream(// 2.构造文件输入流FileInputStreamnew FileInputStream(file)));}
}
8.5 装饰器
  • 如同“俄罗斯套娃”一般层层嵌套
  • 其实装饰器模式在Java开发工具包(Java Development Kit,JDK)里就有大量应用
    • 例如“java.io”包里一系列的流处理类InputStream、FileInputStream、BufferedInputStream、ZipInputStream等
  • 举个例子,当对压缩文件进行解压操作时,我们就会用构造器嵌套结构进行文件流装饰,如:ab.Client.test2()
8.6 自由嵌套
  • 装饰器模式最终的目的就在于“装饰”对象
  • 其中装饰器抽象类扮演着至关重要的角色,它实现了组件的通用接口
  • 并且使自身抽象化以迫使子类继承,使装饰器固定特性的延续与多态化成为可能
8.7 装饰器模式的各角色定义
  • Component(组件接口):
    • 所有被装饰组件及装饰器对应的接口标准指定进行装饰的行为方法。如:展示接口Showable。
  • ConcreteComponent(组件实现):
    • 需要被装饰的组件实现组件接口标准,只具备自身未被装饰的原始特性。如:类Girl
  • Decorator(装饰器):
    • 装饰器的高层抽象类,
    • 同样实现组件接口标准且包含一个被装饰的组件
  • ConcreteDecorator(装饰器实现)
    • 继承自装饰器抽象类的具体子类装饰器,可以有多种实现,在被装饰组件对象的基础上为其添加新的特性
    • 如: 粉底类FoundationMakeup、口红类Lipstick
8.8 装饰器模式
  • 装饰器模式可以将不同功能的单个模块规划至不同的装饰器类中
  • 客户端可以根据自己的需求自由搭配各种装饰器,每加一层装饰就会有新的特性体现出来
  • 最终使原始对象的特性动态地得到增强

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • nginx正向代理、反向代理、负载均衡
  • 【C++】构造函数详解
  • 机器人及其相关工科专业课程体系
  • 批量提取PDF指定区域内容到 Excel , 根据PDF文件第一行文字来自动重命名v1.3-附思路和代码实现
  • qt 返回上级页面
  • Java如何使用 HttpClientUtils 发起 HTTP 请求
  • C++(week11): C++基础 第六章:关联式容器 set、map
  • 2 Java的基本程序设计结构(基本语法1)
  • 外包干了1个月,技术明显退步。。。
  • SparkStreaming--scala
  • Apache访问机制配置
  • 阿里通义音频生成大模型 FunAudioLLM 开源
  • el-popover或el-popconfirm中button不展示问题
  • 从零开始学习c++全套通关系列(第二章)万字总结,建议收藏!
  • 混合贪心算法求解地铁线路调度
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 77. Combinations
  • Angular 响应式表单 基础例子
  • git 常用命令
  • mysql中InnoDB引擎中页的概念
  • Python 基础起步 (十) 什么叫函数?
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • Wamp集成环境 添加PHP的新版本
  • win10下安装mysql5.7
  • 闭包,sync使用细节
  • 坑!为什么View.startAnimation不起作用?
  • 盘点那些不知名却常用的 Git 操作
  • 使用putty远程连接linux
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • ######## golang各章节终篇索引 ########
  • #、%和$符号在OGNL表达式中经常出现
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • #预处理和函数的对比以及条件编译
  • $().each和$.each的区别
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (39)STM32——FLASH闪存
  • (C#)一个最简单的链表类
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (ISPRS,2021)具有遥感知识图谱的鲁棒深度对齐网络用于零样本和广义零样本遥感图像场景分类
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)计算机毕业设计ssm电影分享网站
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (算法)Travel Information Center
  • (算法)大数的进制转换
  • (自用)gtest单元测试
  • *Django中的Ajax 纯js的书写样式1
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .Net Web项目创建比较不错的参考文章
  • .NetCore部署微服务(二)