秒懂设计模式--学习笔记(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;
    	    }
    	
    	    @Override
    	    public void show() {
    	        //化妆品粉饰开始
    	        System.out.print("粉饰【");
    	        //被装饰者的原生展示方法
    	        showable.show();
    	        //粉饰结束
    	        System.out.print("】");
    	    }
    	}
    
    • 装饰器实现类
    	package decorator.entity;
    	import decorator.Showable;
    	/**
    	 * 装饰器实现类
    	 **/
    	public class Girl implements Showable {
    	    @Override
    	    public 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;
    	    }
    	
    	    @Override
    	    public 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);
          }
      
          @Override
          public 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);
          }
      
          @Override
          public 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.构造文件输入流FileInputStream
                        new 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 装饰器模式
  • 装饰器模式可以将不同功能的单个模块规划至不同的装饰器类中
  • 客户端可以根据自己的需求自由搭配各种装饰器,每加一层装饰就会有新的特性体现出来
  • 最终使原始对象的特性动态地得到增强

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/799285.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GUI界面开发之tkinter(一)

Tkinter是一个内置的Python库,用于创建图形用户界面(GUI)。它提供了一组工具和小部件,用于创建窗口、对话框、按钮、菜单和其他GUI元素。 在本篇文章中,主要介绍了窗口等知识点。 大家好!我是码银&#x1…

Nginx实现服务器端集群搭建/Nginx实现动静分离/Nginx高可用解决方案/Nginx与Tomcat部署

Nginx实现服务器端集群搭建 Nginx与Tomcat部署 前面课程已经将Nginx的大部分内容进行了讲解,我们都知道了Nginx在高并发场景和处理静态资源是非常高性能的,但是在实际项目中除了静态资源还有就是后台业务代码模块,一般后台业务都会被部署在Tomcat,weblogic或者是webspher…

把当前img作为到爷爷的背景图

(忽略图大小不一致,一般UI给的图会刚好适合页面大小,我这网上找的图,难调大小,我行内的就自己随便写的宽高),另外悄悄告诉你最后有简单方法~~ 先来看看初始DOM结构代码 …

解锁 EasyV「万能子组件」,你的业务展示形式由你定义!

随着可视化业务表达方式的不断拓深,展示形式也越来越丰富多样,充满更多的“个性化”以及“专属定制”的诉求场景。而现在的子组件样式,仅支持固定格式的内容表达,难以满足易知微用户的定制化需求。 比如以下场景 想在地图上展示图…

破解快消行业营销费用管理难题,引领财务费控数字化转型

众所周知,快消品行业消费群体较为广泛,涉及渠道复杂,产品周转期短、可替代性强,特别是面对竞争激烈的市场环境,大力投入营销、渠道费用对快消行业的企业来说十分普遍,而这其中,由于渠道多、业态…

13.FreeRTOS_定时器

定时器概述 定时器运行过程 定时器就像一个闹钟,它有超时时间、函数、是否为周期性这三个部分。 超时时间:什么时候到时间,就像闹钟响起函数:闹钟响起,要干什么是否为周期性:这个闹钟只响一次&#xff0…

MySQL下载安装使用教程图文教程(超详细)

「作者简介」:冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础著作 《网络安全自学教程》,适合基础薄弱的同学系统化的学习网络安全,用最短的时间掌握最核心的技术。 这一章节我们使…

指针!!C语言(第一篇)

指针1 指针变量和地址1.取地址操作符(&)2.指针变量和解引用操作符(*) 指针变量的大小和类型指针的运算特殊指针1.viod*指针2.const修饰指针3.野指针 assert断言指针的使用和传址调用1.strlen的模拟实现2.传值调用和传址调用 指针变量和地址 在认识指针之前,我们…

算法力扣刷题记录 四十二【101. 对称二叉树、100.相同的树、572.另一个树的子树】

前言 二叉树篇,开始对二叉树操作练习。 记录 四十二【101. 对称二叉树】。 继续。 一、题目阅读 给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输入:root [1,2,2,3,4,4,3] 输出:true示例 2&#x…

香橙派AIpro部署YOLOv5:探索强悍开发板的高效目标检测能力

香橙派AIpro部署YOLOv5:探索强悍开发板的高效目标检测能力 一、香橙派AIpro开箱使用体验 1.1香橙派AIpro开箱 拿到板子后第一件事情就是开箱: 开箱后可以看见一个橘子的标识,也就是香橙派了,并且还有四个大字:为AI…

微信小游戏 彩色试管 倒水游戏 逻辑 (二)

最近开始研究微信小游戏,有兴趣的 可以关注一下 公众号, 记录一些心路历程和源代码。 定义一个 Water class 1. **定义接口和枚举**: - WaterInfo 接口定义了水的颜色、高度等信息。 - PourAction 枚举定义了水的倒动状态,…

基于5个K7的多FPGA PCIE总线架构的高性能数据预处理平台

板载FPGA实时处理器:XCKU060-2FFVA15172个QSFP光纤接口,最大支持10Gbps/lane板载DMA控制器,能实现双向DMA高速传输支持x8 PCIE主机接口,系统带宽5GByte/s1个R45自适应千兆以太网口1个FMC子卡扩展接口 基于PCIE总线架构的高性能数据…

【JavaEE】网络编程——TCP

🤡🤡🤡个人主页🤡🤡🤡 🤡🤡🤡JavaEE专栏🤡🤡🤡 文章目录 前言1.网络编程套接字1.1流式套接字(TCP)1.1.1特点1.1.2编码1.1.2.1ServerSo…

同四千价位闺蜜机,当贝PadGO Air和KTCPro谁更好?

市面上闺蜜机品牌那么多,那么在4K这个价位,如果想购买一台高性价比的闺蜜机应该选择当贝PadGO Air还是KTCPro呢?我们一起来看一下对比 一、外观对比 当贝PadGO Air机身底部为CD型底盘设计,非常有设计感及美感。并且创新性地融入了磁吸快拆布面设计,极大提升了用户体验的便捷…

编程入门(九)【linux系统下docker的部署与发布网站】

读者大大们好呀!!!☀️☀️☀️ 👀期待大大的关注哦❗️❗️❗️ 🚀欢迎收看我的主页文章➡️木道寻的主页 文章目录 🔥前言🚀什么是docker?🚀docker三要素🚀linux系统下docker的基…

算法题-字符串

1.C字符串 c提供了一下两种类型的字符串表示形式: c风格字符串c引入的string类类型 1.1C风格字符串 C 风格的字符串起源于 C 语言,并在 C 中继续得到支持。字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此,一个以 null 结尾的…

KnoBo:医书学习知识,辅助图像分析,解决分布外性能下降和可解释性问题

KnoBo:从医书中学习知识,辅助图像分析,解决分布外性能下降问题 提出背景KnoBo 流程图KnoBo 详解问题构成结构先验瓶颈预测器参数先验 解法拆解逻辑链对比 CLIP、Med-CLIPCLIPMed-CLIPKnoBo 训练细节预训练过程OpenCLIP的微调 构建医学语料库文…

【Nuxt3】vue3+tailwindcss+vuetify引入自定义字体样式

一、目的 在项目中引入自定义的字体样式(全局页面都可使用) 二、步骤 1、下载好字体 字体的后缀可以是ttf、otf、woff、eot或者svg(推荐前三种) 以抖音字体为例下载好放在静态文件夹(font)下 案例字…

notepad++中文出现异体汉字,怎么改正

notepad显示异体字,如何恢复? 比如 “门” 和 “直接” 的"直"字,显示成了 方法 修改字体, 菜单栏选择 Settings(设置),Style Configurator…(语言格式设置…)&#xf…

《昇思25天学习打卡营第22天|onereal》

文本解码原理--以MindNLP为例 回顾:自回归语言模型 根据前文预测下一个单词 一个文本序列的概率分布可以分解为每个词基于其上文的条件概率的乘积 𝑊_0:初始上下文单词序列𝑇: 时间步当生成EOS标签时,停止生成。 MindNLP/huggi…