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

news2024/11/15 4:50:39

目录

      • 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 装饰器模式
  • 装饰器模式可以将不同功能的单个模块规划至不同的装饰器类中
  • 客户端可以根据自己的需求自由搭配各种装饰器,每加一层装饰就会有新的特性体现出来
  • 最终使原始对象的特性动态地得到增强

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VBA即用型代码手册:根据预定义的文本条件删除行

我给VBA下的定义:VBA是个人小型自动化处理的有效工具。可以大大提高自己的劳动效率,而且可以提高数据的准确性。我这里专注VBA,将我多年的经验汇集在VBA系列九套教程中。 作为我的学员要利用我的积木编程思想,积木编程最重要的是积木如何搭建…

Everything搜索无法搜索到桌面的文件(无法检索C盘 或 特定路径的文件)

现象描述 在Everything搜索框中输入桌面已存在的文件或随便已知位置的文件,无法找到。 搜索时检索结果中明显缺少部分磁盘位置的,例如无法检索C盘,任意关键字搜索时结果中没有位于C盘的,无论怎样都搜不到C盘文件。 解决方法 在…

私活必备框架!终于找到一个前后端都有的后台管理系统了~

大家好,我是「程序视点」爱分享的小二哥~ 今天介绍一个新的Vue后台管理框架,相比其他后台功能丰富管理系统,这个后台管理系统可以用干净简洁来形容——Nova-admin Nova-admin Nova-admin 是一个基于Vue3、Vite5等最新技术的后台管理平台。用…

【实战场景】@Transactional中使用for update的注意点

【实战场景】Transactional中使用for update的注意点 开篇词:干货篇:知识回顾注意点1.锁的范围和粒度:2.事务的隔离级别:3.死锁:4.性能影响:5.事务的边界:6.异常处理:7. 数据库和存储…

Xinstall揭秘:APP推广数据背后的真相,让你的营销更精准!

在这个移动互联网时代,APP如同雨后春笋般涌现,但如何在这片红海中脱颖而出,成为每一个开发者与运营者面临的共同难题。其中,APP推广统计作为衡量营销效果、优化推广策略的关键环节,更是不可忽视的一环。今天&#xff0…

【java计算机毕设】学生项目竞赛管理系统 MySQL ssm JSP maven小组项目设计代码源码+万字文档

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】学生项目竞赛管理系统 MySQL ssm JSP maven小组项目设计代码源码万字文档 2项目介绍 系统功能: 学生项目竞赛管理系统包括管理员、用户、教师三种角色。 管理员功能包括个人中心模块用于修改个…

JS进阶-构造函数

学习目标: 掌握构造函数 学习内容: 构造函数 构造函数: 封装是面向对象思想中比较重要的一部分,js面向对象可以通过构造函数实现的封装。 同样的将变量和函数组合到了一起并能通过this实现数据的共享,所不同的是借助…

SA8317E单通道 2.7-15.0V 持续电流 2.5A H 桥驱动芯片

描述 SA8317E 是为消费类产品,小家电和其他 低压或者电池供电的运动控制类应用提供 了一个集成的电机驱动器解决方案。此器 件能够驱动一个直流电机,由一个内部电 荷泵生成所需的栅极驱动电压电路和 4 个 功率 NMOS 组成 H 桥驱动,集成了电…

机器学习和AI智能写作对未来文案编辑的影响

欢迎关注小知:知孤云出岫 目录 机器学习和AI智能写作对未来文案编辑的影响1. 简介2. AI智能写作工具的现状3. AI智能写作的优势3.1 提高效率3.2 降低成本3.3 数据驱动的个性化 4. AI智能写作的挑战4.1 创造力和独创性4.2 道德和伦理问题4.3 技术限制 5. 行业变化5.…

scss概念及使用

目录 scss是什么 scss和css比较 scss的使用 声明变量 区分默认变量 区分全局变量和局部变量 嵌套语法 选择器嵌套 基本嵌套 嵌套中的父选择器引用(&) 嵌套的注意事项 嵌套的嵌套 属性嵌套 基本属性嵌套 嵌套的注意事项 继承 基本用…

python学习-错误与异常

代码是人的逻辑思维的具体体现,因为没有一个人的逻辑思维是完美无缺的,所以人在编写代码时必然会出现各种错误。既然错误或多或少都会发生,那么如何捕捉错误,并且捕捉到错误后要如何处理,就显得很重要。 语法错误 Py…

Win10屏幕录制,这3种方法分享给你

数字化时代里,电脑的屏幕录制功能已经不再是简单的工具,而是成为我们表达、学习和交流的重要媒介。Win10系统依然是大部分人使用的电脑系统,那么关于Win10屏幕录制,有哪些好用高效的录制软件,能够帮助我们更加深入地捕…

【postgresql】视图(View)

PostgreSQL 中的视图(View)是一种虚拟表,其内容由 SQL 查询定义。视图可以简化复杂的 SQL 操作,使得用户能够以一种更直观、更易于理解的方式来访问和操作数据。 PostgreSQL 视图是只读的,因此可能无法在视图上执行 D…

【JavaEE】进程

目录 一.冯诺依曼体系结构 二.CPU的核心概念 核心数 频率(Clock Speed 或时钟频率) 如何选择合适的CPU 三.指令的执行 1.什么是指令 1.取指令 2.解析指令 3.执行指令 4.访问内存(Memory): 5.写回结果(Write…

回收站删除了是不是彻底删除了 回收站删除了怎么找回 回收站删除了还能找回来吗

电脑删除的数据文件一般不会直接被彻底删除掉,而是会暂存在回收站中,这样设计主要是为了防止误删除等操作,如果不小心删除了很重要的文件,只需要在回收站对文件进行还原即可。为了让大家更了解回收站,下面给大家详细讲…

在生产环境中打印堆栈信息以排查错误

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] &#x1f4f1…

我们以后坐出租车,是不是都是没司机了?

今天看到一篇帖子 说是广州出现了一种无人驾驶的出租车 确实比较新奇 萝卜快跑 自动驾驶,不是一个新概念了 其实技术已经很成熟了 但是可能因为法律的一些原因 一直没有全面推 在加上现在AI大模型这块,很火 AI自动驾驶 从打车 到接客 再到送到目的地 一…

亚马逊erp跟卖采集之关键词采集

大家好,今天讲这款erp的跟卖采集关键词采集。 打开erp跟卖功能采集任务,点新增任务站点美国,有5种采集方式:关键词、店铺链接、类目ASIN。 选择关键词采集,这里我选择女童装,选择女童板鞋复制粘贴。页数我…

在2018.3没有找到对应的器件库,需要

图中的器件在vivado中没有找到 一、添加器件 发现所有的2018.3的所有器件库,其实都已经安装了,那么意味着2018.3没有办法对该器件进行综合。 二、安装更新版本的vivado 重新安装的2022.2,在选择器件的时候,把所有的器件全部勾选…

关于string的‘\0‘与string,vector构造特点,反迭代器与迭代器类等的讨论

目录 问题一:关于string的\0问题讨论 问题二:C标准库中的string内存是分配在堆上面吗? 问题三:string与vector的capacity大小设计的特点 问题四:string的流提取问题 问题五:迭代器失效 问题六&#xf…