装饰器模式介绍

目录

一、装饰器模式介绍

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{@Overridepublic 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;}@Overridepublic 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);}@Overridepublic 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;}@Overridepublic String read() {try {String result = FileUtils.readFileToString(newFile(filePath), "utf-8");return result;} catch (IOException e) {e.printStackTrace();return null;}}@Overridepublic 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;}@Overridepublic String read() {return wrapper.read();}@Overridepublic 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);}@Overridepublic String read() {return decode(super.read());}@Overridepublic 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 = newEncryptionDataDecorator(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.mzph.cn/news/626928.shtml

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

相关文章

初学者必知的微软.NET6开发环境相关技术介绍

我是荔园微风,作为一名在IT界整整25年的老兵,看到不少初学者在学习编程语言的过程中如此的痛苦,我决定做点什么,我小时候喜欢看小人书(连环画),在那个没有电视、没有手机的年代,这是…

企业数据挖掘平台哪家好?听听客户的真实反馈

泰迪大数据挖掘企业服务平台让数据创造更大的价值,具有拖曳式、免开发建模、可私有化部署、可提供源代码方便定制、全面培训服务丰富模型参考专业建模人员服务等特点。 听听客户真实反馈: 大数据挖掘企业服务平台包含四大产品服务,分别为&…

数据结构学习 jz40 最小的 k 个数

关键词:排序 快排思想 计数排序 大顶堆 题目:库存管理 III 方法一:sort快排,这种方法绝对过不了面试 方法二:快排思想,只排一半。效率最高 方法三:维护一个大小为cnt的最大堆 方法四&#…

ChatGPT:人工智能划时代的标志(文末送书)

🌈个人主页:聆风吟 🔥系列专栏:网络奇遇记、数据结构 🔖少年有梦不应止于心动,更要付诸行动。 文章目录 一. 什么是ChatGPT?二. ChatGPT是如何工作的?三. ChatGPT的应用领域四. ChatGPT的优缺点…

认识Linux指令之 “tar” 指令

01.tar指令(重要) 打包/解包,不打开它,直接看内容 tar [-cxtzjvf] 文件与目录 .... 参数: -c :建立一个压缩文件的参数指令(create 的意思); -x :解开一个压缩文件的参数指令&am…

Webpack 怎么实现按需异步加载模块

要弄懂这个问题,需要先来看关于webpack打包的3个问题。 三个问题 第一个问题 项目中的json文件,如何使用webpack进行处理? 如果我们希望把json文件当做静态配置,例如有如下json文件 {"version": "1.0.0"…

介绍下Redis 的基础数据结构

目录 这周开始学习 Redis,看看Redis是怎么实现的。所以会写一系列关于 Redis的文章。这篇文章关于 Redis 的基础数据。阅读这篇文章你可以了解: 动态字符串(SDS) 链表 字典 三个数据结构 Redis 是怎么实现的。 SDS SDS &#xff…

前端框架前置课Node.js学习(1) fs,path,模块化,CommonJS标准,ECMAScript标准,包

目录 什么是Node.js 定义 作用: 什么是前端工程化 Node.js为何能执行Js fs模块-读写文件 模块 语法: 1.加载fs模块对象 2.写入文件内容 3.读取文件内容 Path模块-路径处理 为什么要使用path模块 语法 URL中的端口号 http模块-创建Web服务 需求 步骤: 案例:浏…

【NI国产替代】NI‑9234,4通道,51.2 kS/s/ch,±5 V,C系列声音与振动输入模块

4通道,51.2 kS/s/ch,5 V,C系列声音与振动输入模块 NI‑9234可以测量来自集成电子压电(IEPE)和非IEPE传感器的信号,例如加速度计、转速计和接近式探针。 NI‑9234还可兼容智能TEDS传感器。\n\nNI‑9234提供了宽动态范围&#xff0c…

开启C++之旅(下):引用、内联函数及现代特性(auto和范围for循环)

上次介绍了:开启C之旅(上):探索命名空间与函数特性(缺省参数和函数重载) 今天就接着进行c入门的知识讲解 文章目录 1.引用1.1引用概念1.2引用特性1.3常引用其他情况 1.4引用使用场景1.4.1做参数1.4.2做返回…

Proxy的使用方法和13种拦截操作

前言 proxy是ES6新推出的方法,功能很强大。属于元编程,也就是修改js本身的一些东西。可以对数组,对象,函数等引用类型的对象进行一些复杂的操作。 其中,大部分人应该最熟悉的莫过于vue3中使用proxy替换了defineProperty,而且还实现了本身defineProperty不能实现的一些东西。 …

在校大学生可以考哪些 ?(38个考证时间表)

这是整理的在校大学生可以考的,有的对报名条件没有要求,有的是高中以上学历,还有一些应届生可以报考的。可以在支付宝搜索【亿鸣证件照】或者微信搜索【随时照】制作这些考证要求的证件照哦 1、教师资格证 2、英语四六级 3、计算机二级 4、普…

JVM实战(19)——JVM调优工具概述

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 学习必须往深处挖&…

代码随想录 Leetcode541. 反转字符串 II

题目&#xff1a; 代码(首刷自解 2024年1月16日&#xff09;&#xff1a; class Solution { public:void reverse(string& s,int left,int right) {char temp;while (left < right) {temp s[left];s[left] s[right];s[right] temp;left;--right;}return;}string rev…

FastDFS 环境搭建及使用详解

文章目录 1、简介1.1 分布式文件系统1.2 FastDFS1.3 FastDFS架构 2、环境搭建2.1 FastDFS安装2.1.1 安装前准备2.1.2 安装包下载2.1.3 安装 libfastcommon2.1.4 安装 libserverframe2.1.5 安装 FastDFS 2.2 FastDFS配置2.2.1 配置tracker2.2.1.1 创建 tracker 工作目录2.2.1.2 …

Android APP开发集成微信登陆流程(手把手新手版)

本文比较适合新手玩家&#xff0c;老玩家就不要看了 昨天整了下微信登陆&#xff0c;乍一看官方文档还有点难懂&#xff01;遂自己整理了下流程&#xff0c;给大家参考参考。 官方文档链接&#xff1a;准备工作 | 微信开放文档微信开发者平台文档https://developers.weixin.q…

晶圆表面缺陷检测现状概述

背景&#xff1a; 晶圆表面缺陷检测设备主要检测晶圆外观呈现出来的缺陷&#xff0c;损伤、毛刺等缺陷&#xff0c;主要设备供应商KLA&#xff0c;AMAT&#xff0c;日立等&#xff0c;其中KLA在晶圆表面检测设备占有市场52%左右。 检测设备分类&#xff1a; 电子束设备和光学…

浅谈安科瑞电流表和频率表在冰岛某木制品工厂的的应用

摘要&#xff1a;用户侧配电系统的智能化、精细化、可视化是当下配电管理的必然趋势。针对用户侧的配电进线回路&#xff0c;设计安装智能仪表&#xff0c;再通过设置仪表参数来实时监控各负载回路的工作状态&#xff1b;提高用能安全、提升设备维护效率、降低维护的人工成本、…

分类预测 | Matlab实现CS-SVM布谷鸟算法优化支持向量机的数据分类预测

分类预测 | Matlab实现CS-SVM布谷鸟算法优化支持向量机的数据分类预测 目录 分类预测 | Matlab实现CS-SVM布谷鸟算法优化支持向量机的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现CS-SVM布谷鸟算法优化支持向量机的数据分类预测。 2.自带数据…

Matlab 使用 DH table 建立的 robot 和实际不符

机器人仿真 想借助 matlab robotics toolbox 来仿真机器人&#xff0c;但是直接输入自己的 DH table 显示出来的 robot 和实际不情况不符。 DH table 建立 robot Build Manipulator Robot Using Kinematic DH Parameters 主要使用 setFixedTransform&#xff0c;DH table 中…