装饰器模式介绍

news2025/1/9 1:41:17

目录

一、装饰器模式介绍

1.1 装饰器模式定义

1.2 装饰器模式原理

1.2.1 模式类图

1.2.2 模式角色说明

1.2.3 举例代码

二、装饰器模式的应用

2.1 需求说明

2.2 需求实现

2.2.1 类图

2.2.2 类图说明

2.2.3 具体实现

2.2.3.1 DataLoader类

2.2.3.2 BaseFileDataLoader类

2.2.3.3 DataLoaderDecorator类

2.2.3.4 EncryptionDataDecorator

2.2.3.5 TestDecorator测试类

三、装饰器模式总结

3.1 装饰器模式优点

3.2 装饰器模式缺点

3.3 装饰器模式适用场景


一、装饰器模式介绍

1.1 装饰器模式定义

装饰模式(decorator pattern) 的原始定义是:动态的给一个对象添加一些额外的职责。就扩展功能而言,装饰器模式提供了一种比使用子类更加灵活的替代方案。

假设现在有有一块蛋糕,如果只有涂上奶油那这个蛋糕就是普通的奶油蛋糕,这时如果我们添加上一些蓝莓,那这个蛋糕就是蓝莓蛋糕。如果我们再拿一块黑巧克力 然后写上姓名、插上代表年龄的蜡烛,这就是变成了一块生日蛋糕。

在软件设计中,装饰器模式是一种用于替代继承的技术,它通过一种无须定义子类的方式给对象动态的增加职责,使用对象之间的关联关系取代类之间的继承关系。

1.2 装饰器模式原理

1.2.1 模式类图

1.2.2 模式角色说明

装饰(Decorator)模式中的角色:

  • 抽象构件(Component)角色 :它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法。它引进了可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
  • 具体构件(Concrete Component)角色 :它是抽象构件类的子类,用于定义具体的构建对象,实现了在抽象构建中声明的方法,装饰类可以给它增加额外的职责(方法)。
  • 抽象装饰(Decorator)角色 :它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护了一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
  • 具体装饰(ConcreteDecorator)角色 : 它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用于扩充对象的行为。

1.2.3 举例代码

package main.java.cn.test.decorator.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:46:19
 * @description 抽象构件类
 */
public abstract class Component {
    //抽象方法
    public abstract void operation();

}

package main.java.cn.test.decorator.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:46:54
 * @description 具体构建类
 */
public class ConcreteComponent extends Component{
    @Override
    public void operation() {
        //基础功能实现(复杂功能通过装饰类进行扩展)
    }
}

package main.java.cn.test.decorator.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:47:38
 * @description 抽象装饰类-装饰者模式的核心
 */
public class Decorator extends Component {
    //维持一个对抽象构件对象的引用
    private Component component;

    //注入一个抽象构件类型的对象
    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        //调用原有业务方法(这里并没有真正实施装饰,而是提供了一个统一的接口,将装饰过程交给子类完成)
        component.operation();
    }
}

package main.java.cn.test.decorator.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:48:48
 * @description 具体装饰类
 */
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation(); //调用原有业务方法
        addedBehavior(); //调用新增业务方法
    }

    //新增业务方法
    public void addedBehavior() {
        //......
    }

}

二、装饰器模式的应用

2.1 需求说明

我们以一个文件读写器程序为例, 演示一下装饰者模式的使用。

2.2 需求实现

2.2.1 类图

2.2.2 类图说明

  • DataLoader

  抽象的文件读取接口DataLoader

  • BaseFileDataLoader

  具体组件BaseFileDataLoader,重写组件 DataLoader 的读写方法

  • DataLoaderDecorator

  装饰器DataLoaderDecorator,这里要包含一个引用 DataLoader 的对象实例 wrapper,同样是重写 DataLoader 方法,不过这里使用wrapper 来读写,并不进行扩展。

  • EncryptionDataDecorator

  读写时有加解密功能的具体装饰器EncryptionDataDecorator,它继承了装饰器 DataLoaderDecorator 重写读写方法。

2.2.3 具体实现

2.2.3.1 DataLoader类
package main.java.cn.test.decorator.V2;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:28:43
 * @description 抽象的文件读取接口DataLoader
 */
public interface DataLoader {
    String read();

    void write(String data);
}

2.2.3.2 BaseFileDataLoader类
package main.java.cn.test.decorator.V2;

import java.io.File;
import java.io.IOException;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:29:10
 * @description 具体实现组件, 重写读写方法
 */
public class BaseFileDataLoader implements DataLoader {
    private String filePath;

    public BaseFileDataLoader(String filePath) {
        this.filePath = filePath;
    }

    @Override
    public String read() {
        try {
            String result = FileUtils.readFileToString(new
                    File(filePath), "utf-8");
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void write(String data) {
        try {
            FileUtils.writeStringToFile(new File(filePath),
                    data, "utf-8");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

2.2.3.3 DataLoaderDecorator类
package main.java.cn.test.decorator.V2;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:33:23
 * @description 装抽象饰者类
 */
public class DataLoaderDecorator implements DataLoader {
    private DataLoader wrapper;

    public DataLoaderDecorator(DataLoader wrapper) {
        this.wrapper = wrapper;
    }

    @Override
    public String read() {
        return wrapper.read();
    }

    @Override
    public void write(String data) {
        wrapper.write(data);
    }
}

2.2.3.4 EncryptionDataDecorator
package main.java.cn.test.decorator.V2;

import java.util.Base64;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:34:28
 * @description 具体装饰者-对文件内容进行加密和解密
 */
public class EncryptionDataDecorator extends DataLoaderDecorator {
    public EncryptionDataDecorator(DataLoader wrapper) {
        super(wrapper);
    }

    @Override
    public String read() {
        return decode(super.read());
    }

    @Override
    public void write(String data) {
        super.write(encode(data));
    }

    //加密操作
    private String encode(String data) {
        try {

            Base64.Encoder encoder = Base64.getEncoder();
            byte[] bytes = data.getBytes("UTF-8");
            String result = encoder.encodeToString(bytes);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    //解密
    private String decode(String data) {
        try {
            Base64.Decoder decoder = Base64.getDecoder();
            String result = new String(decoder.decode(data),
                    "UTF-8");
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

2.2.3.5 TestDecorator测试类
package main.java.cn.test.decorator.V2;

/**
 * @author ningzhaosheng
 * @date 2024/1/12 18:36:41
 * @description 测试类
 */
public class TestDecorator {
    public static void main(String[] args) {
        String info = "name:tom,age:15";
        DataLoaderDecorator decorator = new
                EncryptionDataDecorator(new BaseFileDataLoader("demo.txt"));
        decorator.write(info);
        String data = decorator.read();
        System.out.println(data);
    }
}

三、装饰器模式总结

3.1 装饰器模式优点

  1. 对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加。
  2. 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为。
  3. 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合可以创造出很多不同行为的组合,得到更加强大的对象。
  4. 具体构建类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构建类和具体装饰类,原有类库代码无序改变,符合开闭原则。

3.2 装饰器模式缺点

  1. 在使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值不同,大量的小对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能。
  2. 装饰器模式提供了一种比继承更加灵活、机动的解决方案,但同时也意味着比继承更加易于出错,排错也更加困难,对于多次装饰的对象,在调试寻找错误时可能需要逐级排查,较为烦琐。

3.3 装饰器模式适用场景

  1. 快速动态扩展和撤销一个类的功能场景。 比如,有的场景下对 API 接口的安全性要求较高,那么就可以使用装饰模式对传输的字符串数据进行压缩或加密。如果安全性要求不高,则可以不使用。
  2. 不支持继承扩展类的场景。 比如,使用 final 关键字的类,或者系统中存在大量通过继承产生的子类。

好了,本次分享就到这里,欢迎大家继续阅读《设计模式》专栏其他设计模式内容,如果有帮助到大家,欢迎大家点赞+关注+收藏,有疑问也欢迎大家评论留言!

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

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

相关文章

Spring使用注解管理Bean

引入lib包 Spring对Bean管理的常用注解 Component组件(作用在类上) Spring中提供了Component的三个衍生注解:(功能在目前为止是一致的) Controller WEB层 Service 业务层 Repository 持久层 属性注入的注解:(使用注解注入的方式,可以不用提供set方法) Value 用于注入普…

新增PostgreSQL数据库管理功能,1Panel开源面板v1.9.3发布

2024年1月15日,现代化、开源的Linux服务器运维管理面板1Panel正式发布v1.9.3版本。 在这一版本中,1Panel新增了PostgreSQL数据库管理功能,并且支持设置PHP运行环境扩展模版。此外,我们进行了30多项功能更新和问题修复。1Panel应用…

6个免费好用的 PDF 文件加密软件 [Windows Mac]

加密 PDF 文件使您能够保护它们免受未经授权的访问。当重要信息处于危险之中时,黑客可以访问电子文档。 考虑到它们很容易被黑客入侵,您需要迅速采取行动。避免这种情况的方法之一是使用更适合您需要的 PDF 加密软件。 有很多选项可供选择,…

Linux中DCHP与时间同步

目录 一、DHCP (一)工作原理 1.获取 2.续约 (二)分配方式 (三)服务器配置 1.随机地址分配 2.固定地址分配 二、时间同步 (一)ntpdate (二)chrony …

智云谷再获资本市场青睐,完成数千万元A+轮融资

近日,深圳前海智云谷科技有限公司(以下简称“智云谷”)完成数千万元A轮融资,本轮融资由青松基金独家投资,多维资本担任独家融资财务顾问。本轮融资资金将用于扩大新技术研发投入、智能工厂扩产、加速产品交付&#xff…

openpose环境搭建

编程如画,我是panda! 最近学习要用要openpose,配了三天的环境,快疯了,踩了很多坑,在这里和大家分享一下 目录 前言 一、安装openpose 二、运行openpose 三、常见的两个错误 1. No module named pyopen…

深度学习论文解读分享之diffGrad:一种卷积神经网络优化方法

IEEE TNNLS 2020:diffGrad: 一种卷积神经网络优化方法 题目 diffGrad: An Optimization Method for Convolutional Neural Networks 作者 Shiv Ram Dubey , Member, IEEE, Soumendu Chakraborty , Swalpa Kumar Roy , Student Member, IEEE, Snehasis Mukherjee…

leetcode234. 回文链表

题目 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true示例 2: 输入:hea…

西米支付:到底什么是NFT(数字藏品支付通道)(NFT支付通道)

NFT到底指的是什么呢? 数字藏品的实际意义在于它们打破了传统艺术品的物质形态束缚。数字藏品可以通过虚拟现实和区块链技术进行创作、展示和交易。它们不仅可以满足人们对艺术品的审美需求,还可以成为一种投资和资产保值增值的方式。数字藏品的实际意义…

线控底盘新玩家凶猛!这家企业的ONE-BOX产品正式量产下线

高工智能汽车获悉,12月27日,威肯西科技宣布旗下ONE-BOX线控制动产品--液压解耦制动系统HDBS实现量产下线。该产品将与多个汽车品牌签署量产及定点协议,预计年产量达到60万套。 据了解,作为耀宁科技集团的一级子公司,威…

Javascript 下载方法分享

一、引言 JavaScript是一种广泛使用的编程语言,用于增强网页交互性和动态功能。然而,有时我们需要将JavaScript代码下载并部署到本地服务器或离线环境中。本文将分享一些常用的JavaScript下载方法。 二、直接下载JavaScript文件 手动下载:…

机器学习-决策树

1、什么是决策树? 一种描述概念空间的有效的归纳推理办法。基于决策树的学习方法可以进行不相关的多概念学习,具有简单快捷的优势,已经在各个领域取得广泛应用。 决策树是一种树型结构,其中每个内部结点表示在一个属性上的测试&a…

徐州数字孪生元宇宙赋能工业智能制造,助力传统制造业数字化转型

徐州数字孪生元宇宙赋能工业智能制造,助力传统制造业数字化转型。在徐州市制造业企业数字化转型的过程中,数字孪生技术的应用已经取得了显著成效。一方面,企业的生产效率得到了显著提高,产品质量也得到了有效保障。另一方面&#…

项目管理中,怎么进行项目过程管理?

项目经理在项目管理中会遇到许多问题,其中最令人头痛的莫过于项目计划执行不到位,进度难以跟踪,项目延期严重。这些问题导致项目计划看似存在,但实际上与无计划相差无几。 对于项目团队内部,项目经理常常抱怨团队成员…

Java后端sql编写

Java后端sql编写 注意事项二级目录三级目录 注意事项 在后端编写sql,不要直接编写sql语句进行查询 比如直接在service实现类中写下图这种语句 二级目录 三级目录

thinkphp 命令行执行

1 php 1 which php 查看命令来源 2 ll /usr/bin/php 软连接,来源是php的安装文件的可执行文件php 3 $PATH的作用, 显示当前PATH环境变量,该变量的值由一系列以冒号分隔的目录名组成如下, echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/…

贴纸SDK多少钱?

贴纸已经成为了表达自我、分享情感的重要工具,美摄科技,作为一家领先的技术解决方案提供商,致力于为企业提供卓越的贴纸SDK(软件开发工具包)技术解决方案。本文将深入探讨美摄科技贴纸SDK的价值、优势以及如何为企业创造价值。 一…

K8S----YAML

kubernetes中资源可以使用YAML描述(如果您对YAML格式不了解,可以参考YAML语法),也可以使用JSON。其内容可以分为如下四个部分: typeMeta:对象类型的元信息,声明对象使用哪个API版本&#xff0c…

linux云服务器 如何将数据盘挂载到系统盘上面?

先认识认识下面几个常用命令 lsblk 命令:查看设备列表,也就是能看到系统盘和数据盘一般为:vda(系统盘)、vdb(数据盘)等等 lsblk"ls" 是 "list" 的缩写: lsblk…

❤ uniapp 开发小程序环境搭建和使用零(0 开篇-介绍和运行)

♥ uniapp 环境搭建 1、简单介绍 拿HbuildX写代码开发,然后把程序运行到微信开发者工具 开发uniapp小程序需要用到的两个工具 HbuildX [开发小程序使用] https://www.dcloud.io/hbuilderx.html 微信开发者工具 HbuildX开发的小程序运行到微信开发者工具 https://de…