设计模式之装饰器模式(Decorator)

一、装饰器模式介绍

       装饰模式(decorator pattern) 的原始定义是:动态的给一个对象添加一些额外的职责。

       就扩展功能而言,装饰器模式提供了一种比使用子类更加灵活的替代方案。

       在软件设计中,装饰器模式是一种用于替代继承的技术,它通过一种无须定义子类的方式

       给对象动态的增加职责,使用对象之间的关联关系取代类之间的继承关系。

二、装饰器模式原理

       装饰器模式结构类图如下所示:

              

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

               1)抽象构件(Component)角色 :它是具体构件和抽象装饰类的共同父类,声明了

                     在具体构件中实现的业务方法。它引进了可以使客户端以一致的方式处理未被装

                     饰的对象以及装饰之后的对象,实现客户端的透明操作

               2)具体构件(Concrete  Component)角色 :它是抽象构件类的子类,用于定义具体

                    的构建对象,实现了在抽象构建中声明的方法,装饰类可以给它增加额外的职责

                    (方法)。即被装饰者

               3)抽象装饰(Decorator)角色 :它也是抽象构件类的子类,用于给具体构件增加

                    职责,但是具体职责在其子类中实现。它维护了一个指向抽象构件对象的引用,

                    通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达

                    到装饰的目的。

               4)具体装饰(ConcreteDecorator)角色 : 它是抽象装饰类的子类,负责向构件添加

                     新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中

                     定义的方法,并可以增加新的方法用于扩充对象的行为。   

        装饰者模式中的各个角色用代码表示如下:     

/******************************************************** 抽象构建类(抽象构件),* 抽象构建类可以是抽象类,也可以是接口********************************************************/
public abstract class Component {//抽象方法public abstract void operation();
}/******************************************************** 具体构建类(被装饰类)********************************************************/
public class ConcreteComponent extends Component{@Overridepublic void operation() {//基础功能实现(复杂功能通过装饰类进行扩展)}
}/******************************************************** 抽象装饰类--装饰者模式的核心********************************************************/
public class Decorator extends Component{//维持一个对抽象构件对象的引用private Component component;//注入一个抽象构件类型的对象public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {//调用原有业务方法(这里并没有真正实施装饰,而是提供了一个统一的接口,将装饰过程交给子类完成)component.operation();}
}/******************************************************** 具体装饰类********************************************************/
public class ConcreteDecorator extends Decorator{public ConcreteDecorator(Component component) {super(component);}@Overridepublic void operation() {super.operation(); //调用原有业务方法addedBehavior(); //调用新增业务方法}//新增业务方法public void addedBehavior(){//......}
}

三、装饰器模式应用示例

       以文件读写器程序为例, 演示一下装饰者模式的使用,该示例主要类如下:

               1)DataLoader:抽象的文件读取接口DataLoader ;抽象构件角色

               2)BaseFileDataLoader:具体组件BaseFileDataLoader,重写组件 DataLoader

                     的读写方法;具体构件角色

               3)DataLoaderDecorator:装饰器DataLoaderDecorator,这里要包含一个引用

                     DataLoader 的对象实例 wrapper,同样是重写 DataLoader 方法,不过这里

                     使用 wrapper 来读写,并不进行扩展;抽象装饰者

               4)EncryptionDataDecorator:读写时有加解密功能的具体装饰器

                    EncryptionDataDecorator,它继承了装饰器 DataLoaderDecorator 重写读写方法;

                    具体装饰者

       该示例的UML类图如下:

               

       该示例具体代码如下:

/*** 我们以一个文件读写器程序为例, 演示一下装饰者模式的使用** 抽象的文件读取接口DataLoader--抽象构建类*/
public interface DataLoader {//读String read();//写void write(String data);
}******************************************************** 具体组件,重写方法 -- 具体构建类(被装饰类)********************************************************/
public class BaseFileDataLoader implements DataLoader{//读取/写入 的文件路径private String filePath;public BaseFileDataLoader(String filePath) {this.filePath = filePath;}@Overridepublic String read() {try {String result = FileUtils.readFileToString(new File(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();}}
}/******************************************************** 抽象装饰者类** *******************************************************/
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);}
}/******************************************************** 具体装饰者类--对读取/写入数据 进行加解密* *******************************************************/
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;}}
}//测试
public class Test {public static void main(String[] args) {String info = "name:tom java";DataLoaderDecorator decorator = new EncryptionDataDecorator(new BaseFileDataLoader("demo.txt"));decorator.write(info);String data = decorator.read();System.out.println(data);}
}

四、装饰器模式总结

1、装饰者模式优点

      1)对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加

      2)可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不

            同的具体装饰类,从而实现不同的行为

      3)可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列

           组合可以创造出很多不同行为的组合,得到更加强大的对象

      4)具体构建类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构建类和

           具体装饰类,原有类库代码无序改变,符合开闭原则

2、装饰者模式缺点

      1)在使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相

           互连接的方式有所不同,而不是它们的类或者属性值不同,大量的小对象的产生势必会

          占用更多的系统资源,在一定程度上影响程序的性能

      2)装饰器模式提供了一种比继承更加灵活、机动的解决方案,但同时也意味着比继承更

           加易于出错,排错也更加困难,对于多次装饰的对象,在调试寻找错误时可能需要逐级

           排查,较为烦琐

      

3、装饰者模式适用场景

      1)快速动态扩展和撤销一个类的功能场景。 比如,有的场景下对 API 接口的安全性要求较

            高,那么就可以使用装饰模式对传输的字符串数据进行压缩或加密。如果安全性要求不

            高,则可以不使用。

      2)不支持继承扩展类的场景。 比如,使用 final 关键字修饰的类,或者系统中存在大量通过

            继承产生的子类。

      

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

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

相关文章

【颜色平衡树 / E】

题目 思路 DFS暴力 60分 代码 #include <bits/stdc.h> using namespace std; const int N 5010; const int M 5010; int h[N], e[M], ne[M], idx; int c[N], f; int ans; void add(int a, int b) // 添加一条边a->b {e[idx] b, ne[idx] h[a], h[a] idx ; } …

Linux防火墙-常用命令

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们经过上小章节讲了Linux的部分进阶命令&#xff0c;我们接下来一章节来讲讲Linux防火墙。由于目前以云服务器为主&#x…

C语言—单链表

目录 一、链表的概念及结构 二、单链表实现 &#xff08;2.1&#xff09;基本结构定义 &#xff08;2.2&#xff09;申请节点 &#xff08;2.3&#xff09;打印函数 &#xff08;2.4&#xff09;头部插入删除\尾部插入删除 &#xff08;2.4.1&#xff09;尾部插入 &…

计算机毕业设计 基于Python的人事管理系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

spring揭秘26-springmvc06-springmvc注解驱动的web应用

文章目录 【README】【1】springmvc注解驱动web应用【1.1】springmvc注解驱动web应用的3个组件【1.2】springmvc注解驱动web应用代码实践 【2】springmvc常用注解【2.1】Controller注解&#xff08;标注处理器类&#xff09;【2.2】RequestMapping注解&#xff08;标注处理器类…

OpenAI董事会主席Bret Taylor的Agent公司Sierra:专注于赋能下一代企业用户体验

本文由readlecture.cn转录总结。ReadLecture专注于音、视频转录与总结&#xff0c;2小时视频&#xff0c;5分钟阅读&#xff0c;加速内容学习与传播。 视频来源 youtube: https://www.youtube.com/watch?vriWB5nPNZEM&t47s 大纲 介绍 欢迎与介绍 介绍Bret Taylor&#x…

如 有 任 何 问 题 ,请 及 时 联 系 我 们 反 馈 !

如有任何问题&#xff0c; 请及时联系我们反馈 !https://support.qq.com/products/671606 如有任何问题&#xff0c; 请及时联系我们反馈 !

基金好书入门阅读笔记《基金作战笔记:从投基新手到配置高手的进阶之路》2

买基金&#xff0c;说到底是买基金所持有的一揽子资产。那么&#xff0c;常见的可投资产都有哪些类型呢&#xff1f; 图2.9进行了系统性的梳理&#xff0c;我们把资产分为四大类&#xff0c;分别是权益类、固收类、现金和另 类&#xff0c;下面就一一解读。 年化收益率是把一段…

Bluetooth Channel Sounding中关于CS Procedure的详细介绍

目录 BLE CS 过程定义&#xff1a; BLE CS 过程的组成部分 开始一个BLE CS 过程 与BLE CS过程相关的参数设置 BLE CS 过程定义&#xff1a; BLE 的CS特性包含一组LL层和空口协议的组合过程&#xff0c;该过程可以使得两个BLE 设备以紧密互锁的方式&#xff0c;在多个信道上…

人工智能专业就业方向与前景

随着产业结构升级的持续推进&#xff0c;未来行业领域对于人工智能专业人才的需求量会逐渐增加&#xff0c;一部分高校也开始陆续在本科阶段开设人工智能专业&#xff0c;以缓解人工智能领域人才缺口较大的问题。下面是小编整理的人工智能专业就业方向与前景&#xff0c;欢迎阅…

第五节——转移表(让你不再害怕指针)

文章目录 制作简易计算器什么是转移表&#xff1f;switch函数实现函数指针数组实现 制作简易计算器 要求&#xff1a;制作一个简易计算器&#xff0c;可以进行* / - 等功能运算。 什么是转移表&#xff1f; 指的就是通过函数指针数组的方式通过数组去调用里面的函数&#x…

儿童需要学习C++多久才能参加信息学奥赛的CSP-J比赛?

信息学奥赛&#xff08;NOI&#xff09;是国内编程竞赛领域的顶尖赛事&#xff0c;而对于初学者来说&#xff0c;参加NOI的第一步通常是通过CSP-J&#xff08;全国青少年信息学奥林匹克联赛初赛&#xff09;&#xff0c;这也是面向青少年程序员的入门级竞赛。作为信息学奥赛的基…

DDR6 或将出炉 (含 LPDDR6, CAMM)

前记:目前DDR6 尚未问世,文中较多信息是“据说”,笔者也无法考证,请大家后期以JEDEC官方为准。 很多朋友可能还没用上DDR5,但不好意思的是,DDR6 可能马上就要出现了。 三星和海力士较早开始DDR6 的设计,预计2025年商业化。 DDR6 速度 来源: 半导体观察 DDR6的速度…

AcWing 662:点的坐标 ← 结构体 or 三目运算符

【题目来源】https://www.acwing.com/problem/content/664/【题目描述】 给定两个保留一位小数的浮点数 X,Y&#xff0c;用来表示一个点的横纵坐标。 请你判断该点在坐标系中的位置。 【输入格式】 共一行&#xff0c;包含两个浮点数 X,Y&#xff0c;表示点的横纵坐标。【输出格…

毕业设计 深度学习社交距离检测系统(源码+论文)

文章目录 0 前言1 项目运行效果2 设计原理3 相关技术3.1 YOLOV43.2 基于 DeepSort 算法的行人跟踪 4 最后 0 前言 &#x1f525;这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;…

卷积层是如何学习到图像特征的?

你好啊&#xff0c;我是董董灿。 想搞懂这个问题&#xff0c;需要先了解我们所说的特征指的是什么&#xff1f;然后再了解卷积核是如何学到的特征。 我们一步步来。 1、我们先来理解图像的特征 对于一张原始图像而言&#xff0c;说原始图像是相对于经过卷积处理而言的。 对…

VL53L4CD液位监测(2)----液位检测

VL53L4CD液位监测.2--液位检测 概述视频教学样品申请完整代码下载硬件准备STSW-IMG039容器特性包含必要的头文件变量定义测距函数 Ranging()液位误差补偿函数 Liquidlevelmeasureerrorcomponsate()数据轮询函数 get_data_by_polling()演示 概述 液位检测在工业自动化、环境监测…

十大时间序列预测模型

目录 1. 自回归模型 原理 核心公式 推导过程: 完整案例 2. 移动平均模型 原理 核心公式 推导过程: 完整案例 3. 自回归移动平均模型 原理 核心公式 推导过程: 完整案例 4. 自回归积分移动平均模型 原理 核心公式 推导过程 完整案例 5. 季节性自回归积分…

LeetCode讲解篇之695. 岛屿的最大面积

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们遍历二维矩阵&#xff0c;如果当前格子的元素为1进行深度优先搜索&#xff0c;将搜索过的格子置为0&#xff0c;防止重复访问&#xff0c;然后对继续深度优先搜索上下左右中为1的格子 题解代码 func maxAr…

【通信协议】一文学会异步、同步、串行、并行、单工、半双工、全双工(一)

通信方式详解&#xff1a;异步、同步、串行、并行、单工、半双工、全双工 引言一、通信方式分类概述二、串行通信与并行通信串行通信 (Serial Communication)并行通信 (Parallel Communication)串行与并行通信对比表 三、全双工、半双工、单工通信单工通信 (Simplex Communicat…