设计模式-装饰器模式(结构型)与责任链模式(行为型)对比,以及链式设计

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 1.装饰器模式
    • 1.1概念
    • 1.2作用
    • 1.3应用场景
    • 1.4特点
    • 1.5类与对象关系
    • 1.6实现
  • 2责任链模式
    • 2.1概念
    • 2.2作用
    • 2.3应用场景
    • 2.4特点
    • 2.5类与对象关系
    • 2.6实现
  • 3.对比
  • 总结


前言

装饰器模式和设计模式同为GoF23中设计模式之一,两者在结构上有相似之处,本文章用来学习两个设计模式,并进行对比。


1.装饰器模式

1.1概念

如果我们想要为一个已经写好的类增加新功能,在不修改该类源码的情况下,我们有以下选择:

  • 创建该类的子类,并用该子类调用父类方法,并额外添加其他功能
  • 创建一个新的类,引用已有类的对象,调用原有方法并添加其他功能

这里第二种实现思路就是我们现在说的装饰器模式。

1.2作用

为一个已有的类增加新的功能。

1.3应用场景

  • 需要动态地给对象添加职责时:当你需要给某个对象添加职责,但又不想修改其类定义时,可以使用装饰器模式。
  • 需要灵活组合多个职责时:当你有多个职责需要组合,并且这些职责的排列组合可能会变化时,装饰器模式是一个很好的选择。
  • 需要保持类的单一职责原则时:当你想保持类的单一职责原则,但又需要给类添加额外的职责时,可以使用装饰器模式将这些职责分离到装饰器

1.4特点

  • 动态扩展:装饰器模式能够在运行时动态地给对象添加职责,而无需修改类的定义。
  • 灵活性:通过组合的方式而不是继承来扩展功能,这使得装饰器模式比继承更加灵活。
  • 遵循开闭原则:装饰器模式可以在不修改现有代码的情况下添加新的功能,符合开闭原则(对扩展开放,对修改关闭)。
  • 装饰器与被装饰对象拥有相同的接口:这使得装饰器可以透明地替代被装饰对象

1.5类与对象关系

在这里插入图片描述

  • 组件接口:对应上图Component,用来规定被装饰对象和装饰器应该有哪些功能(或者说原组件中哪些功能是可以装饰的)
  • 组件类:对应上图ConcreteComponent,是被装饰对象
  • 抽象装饰器:对应上图Decorator,是一个接口,因为我们会有多个不同的具体装饰器,所以需要使用一个抽象装饰器接口来指定具体装饰器应该有哪些功能
  • 具体装饰器:是我们真正的额外功能编写的地方,因为实现了抽象装饰器所以拥有与被装饰对象相同但更强大的功能,可以在使用时进行替换。

1.6实现

// 定义一个接口,规定哪些方法可以被装饰
interface Component {void operation();
}// 具体组件类,实现了Component接口
class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}// 抽象装饰器类,持有一个Component对象,并实现了Component接口
abstract class Decorator implements Component {// 该对象存储原对象或者被其他装饰器装饰过的对象// 因为可以是其他装饰器装饰过的对象,所以才实现装饰器的叠加,是动态添加功能的关键protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}// 具体装饰器类A,增加了额外的行为
class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("ConcreteDecoratorA added behavior");}
}// 具体装饰器类B,增加了额外的行为
class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}@Overridepublic void operation() {addedBehavior();super.operation();}private void addedBehavior() {System.out.println("ConcreteDecoratorB added behavior");}
}// 客户端代码
public class DecoratorPatternDemo {public static void main(String[] args) {Component component = new ConcreteComponent();// 使用装饰器A装饰Component decoratorA = new ConcreteDecoratorA(component);// 使用装饰器B装饰装饰器AComponent decoratorB = new ConcreteDecoratorB(decoratorA);// 执行操作,将展示所有组件和装饰器的行为decoratorB.operation();}
}

2责任链模式

2.1概念

责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行传递。每个处理者可以对请求进行处理,或者将请求传递给链中的下一个处理者。这使得你可以在不明确具体接收者的情况下,向多个对象发送请求。

2.2作用

  • 解耦请求与处理:请求者只要向链头发送一次请求,而不用关心具体由谁处理。
  • 可以动态管理处理类:可以按需添加或删除处理类。

2.3应用场景

  • 多个对象有机会处理请求:当请求可以在多个对象之间传递,并且每个对象都有可能处理它时。
  • 请求处理顺序可变:当请求的处理顺序不固定,或者你想在不修改代码的情况下改变处理顺序时。
  • 解耦请求发送者和处理者:当你想解耦请求发送者和处理者之间的依赖关系时。

2.4特点

  • 链式传递:请求在多个处理者之间传递,直到有一个处理者处理它或链结束。
  • 解耦请求发送者和接收者:发送者不需要知道哪个具体的处理者会处理请求,它只需要将请求发送到链的头部即可。
  • 增强灵活性:你可以通过动态地添加或删除处理者来改变链的结构,从而改变请求的处理流程。

2.5类与对象关系

在这里插入图片描述

责任链模式中我们有以下角色:

  • 抽象处理者(Handler)角色:声明“处理”方法,以及一个“设置下一处理器”的方法
  • 具体处理者(Concrete Handler)角色:实现了抽象处理者接口,并包含处理请求的逻辑。如果它不能处理请求,它会将请求传递给链中的下一个处理者。

2.6实现

// 抽象处理者接口
abstract class Handler {protected Handler nextHandler;// 设置下一个处理者public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}// 处理请求的方法,由具体处理者实现public abstract void handleRequest(String request);
}// 具体处理者类A
class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if ("A".equals(request)) {System.out.println("ConcreteHandlerA handled request: " + request);} else {if (nextHandler != null) {nextHandler.handleRequest(request);}}}
}// 具体处理者类B
class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if ("B".equals(request)) {System.out.println("ConcreteHandlerB handled request: " + request);} else {if (nextHandler != null) {nextHandler.handleRequest(request);}}}
}// 客户端代码
public class ChainOfResponsibilityDemo {public static void main(String[] args) {// 创建处理者对象Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();// 构建处理者链handlerA.setNextHandler(handlerB);// 创建并发送请求String[] requests = {"A", "B", "C"};for (String request : requests) {handlerA.handleRequest(request); // 请求从handlerA开始传递}}
}

3.对比

  1. 首先,链式设计最重要的一点是——一个节点中要存储相邻节点的信息,这一点在上述两种设计模式中都有体现。这里要先清楚各自具体存储的是什么。
  • 装饰器模式存储的是原组件或被修饰过的组件,这说明在该种模式下各个装饰器的作用是可以叠加的
  • 责任链模式存储的是下一个处理节点,这里各个处理器效果并不会叠加
  1. 其次,各个节点应该有同样的任务。这两种模式中不论是各个装饰器,还是各个处理器,其实都有同样的任务。但是两个模式在具体实现时有区别,这也是装饰器模式可叠加而责任链模式不可叠加的原因。
  • 装饰器中的方法逻辑是——上一节点处理逻辑"及"本节点处理逻辑
  • 责任链中的方法逻辑是——本节点处理逻辑"或"下节点处理逻辑

总结

本文章比较了装饰器模式和责任链模式,因为两者在结构上十分相似都使用了链式设计,所以容易混淆,这里需要重点理解两者在处理方法中的实现逻辑的不同,装饰器是"且",责任链是"或"。

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

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

相关文章

操作系统:死锁与饥饿

目录 死锁概念 饥饿与饿死概念 饥饿和死锁对比 死锁类型 死锁条件(Coffman条件) 死锁恢复方法 死锁避免 安全状态与安全进程序列: 银行家算法: 死锁检测时机(了解): 死锁检测 死锁案…

RPO: Read-only Prompt Optimization for Vision-Language Few-shot Learning

文章汇总 想解决的问题对CoOp的改进CoCoOp尽管提升了性能,但却增加了方差(模型的准确率波动性较大)。 模型的框架一眼看去,跟maple很像(maple跟这篇文章都是2023年发表的),但maple的视觉提示是由文本提示经过全连接转换而来的,而这里是文本提示和视觉提示是独立的。另外m…

『MySQL 实战 45 讲』24 - MySQL是怎么保证主备一致的?

MySQL是怎么保证主备一致的? MySQL 主备的基本原理 基本的主备切换流程 状态 1:客户端的读写都直接访问节点 A,而节点 B 是 A 的备库状态 2:切换时,读写访问的都是节点 B,而节点 A 是 B 的备库注意&…

自荐一部IT方案架构师回忆录

作者本人毕业于一个不知名大专院校,所读专业计算机科学技术。2009年开始IT职业生涯,至今工作15年。擅长TSQL/Shell/linux等技术,曾经就职于超万人大型集团、国内顶级云厂商、央国企公司。参与过运营商大数据平台、大型智慧城市ICT、云计算、人…

python数据分析之爬虫基础:selenium详细讲解

目录 1、selenium介绍 2、selenium的作用: 3、配置浏览器驱动环境及selenium安装 4、selenium基本语法 4.1、selenium元素的定位 4.2、selenium元素的信息 4.3、selenium元素的交互 5、Phantomjs介绍 6、chrome handless模式 1、selenium介绍 (1…

【数据结构——查找】顺序查找(头歌实践教学平台习题)【合集】

目录😋 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:实现顺序查找的算法。 相关知识 为了完成本关任务,你需要掌握:1.根据输入数据建立顺序表,2.顺序表的输出,…

create-react-app react19 搭建项目报错

报错截图 此时运行会报错: 解决方法: 1.根据提示安装依赖法 执行npm i web-vitals然后重新允许 2.删除文件法 在index.js中删除对报错文件的引入,删除报错文件

Scratch 消灭字母小游戏

背景 最近尝试一边自学Scratch,一边尝试教给小孩,看他打字时在键盘上乱打一气,想起来自己小时候玩过的学习机打字母游戏,就想给他下载一个。结果网上看到的代码,要么质量太差(有26个字母就要写 26 个判断&…

python调用matlab函数(内置 + 自定义) —— 安装matlab.engine

文章目录 一、简介二、安装matlab.engine2.1、基于 CMD 安装2.2、基于 MATLAB 安装(不建议) 三、python调用matlab函数(内置 自定义) 一、简介 matlab.engine(MATLAB Engine API for Python):…

pytroch环境安装-pycharm

环境介绍 安装pycharm 官网下载即可,我这里已经安装,就不演示了 安装anaconda 【官网链接】点击下载 注意这一步选择just me 这一步全部勾上 打开 anaconda Prompt 输入conda create -n pytorch python3.8 命令解释:创建一个叫pytorch&…

Photoshop提示错误弹窗dll缺失是什么原因?要怎么解决?

Photoshop提示错误弹窗“DLL缺失”:原因分析与解决方案 在创意设计与图像处理领域,Photoshop无疑是众多专业人士和爱好者的首选工具。然而,在使用Photoshop的过程中,有时会遇到一些令人头疼的问题,比如突然弹出的错误…

上海亚商投顾:创业板指震荡调整 机器人概念股再度爆发

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 沪指昨日冲高回落,深成指、创业板指盘中跌超1%,尾盘跌幅有所收窄。机器人概念股逆势爆…

(Linux)CentOS7离线安装MinIO(超详细)

目录 前言1. 下载2. 安装VMware3. 安装CentOS4. 离线安装MinIO4.1. ssh工具连接CentOS4.2. 上传MinIO离线包4.2.1 创建data目录4.2.2 上传RPM包到data目录4.2.3 安装RPM包4.2.4 创建MinIO数据目录4.2.5 配置 MinIO 服务4.2.6 启动 MinIO4.2.7 开放端口 4.2.8 访问MinIO 创作不易…

HarmonyOS-高级(四)

文章目录 应用开发安全应用DFX能力介绍HiLog使用指导HiAppEvent 🏡作者主页:点击! 🤖HarmonyOS专栏:点击! ⏰️创作时间:2024年12月11日11点18分 应用开发安全 应用隐私保护 隐私声明弹窗的作…

论文阅读:Statistical Comparisons of Classifiers over Multiple Data Sets

论文地址:Statistical Comparisons of Classifiers over Multiple Data Sets (acm.org) 前面在机器学习之Friedman检验-CSDN博客 中提到了Friedman检验,这里将对这个方法的论文进行详细的阅读,以了解其原理。 摘要 尽管用于在单个数据集上比…

练9:进制转换

欢迎大家订阅【蓝桥杯Python每日一练】 专栏,开启你的 Python数据结构与算法 学习之旅! 文章目录 1 进制转换2 例题分析 1 进制转换 ①任意制转为十进制 【示例】 ②十进制转为任意制 【法一】 【法二】 2 例题分析 题目地址:https:/…

C语言:指针详解续

一、字符指针变量 我们知道有种指针类型为字符指针(char*)。 #include <stdio.h> int main() {char ch w;char* pch &ch;printf("%c\n", *pch);return 0; } 其实它还有一种使用方式。 #include <stdio.h> int main() {char* pstr "hello…

HarmonyOS-高级(一)

文章目录 一次开发、多端部署自由流转 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;HarmonyOS专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月09日12点19分 一次开发、多端部署 布局能力 自适应布局 拉伸能力均分能力占比能力缩放…

【嵌入式系统】第4章 嵌入式最小系统,供电电路,时钟电路,复位电路,程序下载电路

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…

期权懂|交易个股期权需要注意哪些风险?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 交易个股期权需要注意哪些风险&#xff1f; 一、交易个股期权需要注意合约到期风险&#xff1a; 需关注到期日&#xff0c;及时平仓或行权&#xff0c;避免合约作废。二、交易个…