Python 如何实现职责链设计模式?什么是职责链设计模式?Python 职责链设计模式示例代码

什么是职责链(Chain of Responsibility)设计模式?

职责链(Chain of Responsibility)设计模式是一种行为型设计模式,旨在构建一个对象链,每个对象都有机会处理请求,并且可以将请求传递给链中的下一个对象。

在这里插入图片描述

在这个模式中,请求沿着链条依次传递,直到其中的某个对象处理请求为止。每个处理器(Handler)对象都包含一个指向下一个处理器的引用,形成了一个链式结构。请求进入链条的顶端,并从顶端的处理器开始处理,若顶端处理器无法处理该请求,它会将请求传递给下一个处理器,直至找到合适的处理器为止。
在这里插入图片描述
这种模式的主要目的是解耦发送者和接收者,使多个对象都有机会处理请求,而不需要明确指定请求的接收者。这样可以增强系统的灵活性,因为发送者不需要知道请求最终会由哪个对象处理,同时也可以动态地调整和扩展处理器链。

主要角色:
  1. 抽象处理者(Handler): 定义了处理请求的接口,通常包含一个指向下一个处理者的引用(后继者)。该角色提供一个处理请求的方法,通常是一个抽象方法或者是一个虚拟方法,子类需要实现该方法。抽象处理者可以决定是否将请求传递给下一个处理者。

  2. 具体处理者(ConcreteHandler): 实现了抽象处理者定义的接口,在收到请求时负责处理请求。如果能够处理请求,则直接进行处理;如果不能处理,则将请求传递给下一个处理者。

优点:
  1. 解耦发送者和接收者: 发送者无需知道请求的具体处理者,降低了发送者和接收者之间的耦合度,增强了系统的灵活性。

  2. 动态的请求处理流程: 可以动态地改变和调整处理请求的顺序和流程,增加了灵活性和可扩展性。

  3. 单一职责原则: 每个具体处理者只负责处理自己能够处理的请求,遵循了单一职责原则。

  4. 可拓展性: 可以灵活地新增、删除或调整处理者,以适应不同的业务需求。

  5. 简化了对象之间的连接: 无需发送者了解整个处理链的结构,只需要将请求发送给链条的起始处理者即可。

缺点:
  1. 请求未必被处理: 如果没有合适的处理者处理请求,可能会导致请求未被处理。

  2. 链过长可能影响性能: 如果处理链过长,可能会影响性能,因为请求需要在整个链条上进行传递和寻找处理者。


Python 职责链设计模式示例代码(一):

假设我们要实现在线支付系统中,需要根据用户的信用评级给予不同的授信额度。这个场景可以使用职责链模式来实现。

from abc import ABC, abstractmethod# 抽象处理者
class CreditHandler(ABC):def __init__(self, successor=None):self.successor = successordef set_successor(self, successor):self.successor = successor@abstractmethoddef check_credit(self, user):pass# 具体处理者1 - 优秀信用用户
class ExcellentCreditHandler(CreditHandler):def check_credit(self, user):if user['credit_score'] >= 80:print(f"Excellent credit score for {user['name']}. Credit limit: 50000")elif self.successor:self.successor.check_credit(user)# 具体处理者2 - 良好信用用户
class GoodCreditHandler(CreditHandler):def check_credit(self, user):if 60 <= user['credit_score'] < 80:print(f"Good credit score for {user['name']}. Credit limit: 20000")elif self.successor:self.successor.check_credit(user)# 具体处理者3 - 一般信用用户
class FairCreditHandler(CreditHandler):def check_credit(self, user):if user['credit_score'] < 60:print(f"Fair credit score for {user['name']}. Credit limit: 10000")elif self.successor:self.successor.check_credit(user)# 客户端代码
if __name__ == "__main__":# 用户信息user1 = {'name': '张三', 'credit_score': 85}user2 = {'name': '李四', 'credit_score': 70}user3 = {'name': '王五', 'credit_score': 50}# 创建处理者链excellent_handler = ExcellentCreditHandler()good_handler = GoodCreditHandler()fair_handler = FairCreditHandler()# 设置处理者顺序excellent_handler.set_successor(good_handler)good_handler.set_successor(fair_handler)# 发送请求excellent_handler.check_credit(user1)excellent_handler.check_credit(user2)excellent_handler.check_credit(user3)

这个示例模拟了一个根据用户信用评级给予不同授信额度的场景。根据用户的信用评级,不同的处理者会决定用户的授信额度,如果用户信用评级不符合任何处理者的条件,则不给予授信。


Python 职责链设计模式示例代码(二):

假设我们有一个在线购物系统,需要根据用户的会员等级给予不同的优惠。这个场景可以用职责链模式来实现。

from abc import ABC, abstractmethod# 抽象处理者
class DiscountHandler(ABC):def __init__(self, successor=None):self.successor = successordef set_successor(self, successor):self.successor = successor@abstractmethoddef apply_discount(self, user, amount):pass# 具体处理者1 - VIP会员折扣
class VIPDiscountHandler(DiscountHandler):def apply_discount(self, user, amount):if user['is_vip']:print(f"VIP discount applied for {user['name']}. Final amount: {amount * 0.7}")elif self.successor:self.successor.apply_discount(user, amount)# 具体处理者2 - 普通会员折扣
class RegularDiscountHandler(DiscountHandler):def apply_discount(self, user, amount):if user['is_regular']:print(f"Regular member discount applied for {user['name']}. Final amount: {amount * 0.9}")elif self.successor:self.successor.apply_discount(user, amount)# 具体处理者3 - 无折扣
class NoDiscountHandler(DiscountHandler):def apply_discount(self, user, amount):print(f"No discount applied for {user['name']}. Final amount: {amount}")# 客户端代码
if __name__ == "__main__":# 用户信息user1 = {'name': 'Alice', 'is_vip': True, 'is_regular': False}user2 = {'name': 'Bob', 'is_vip': False, 'is_regular': True}user3 = {'name': 'Eve', 'is_vip': False, 'is_regular': False}# 创建处理者链vip_handler = VIPDiscountHandler()regular_handler = RegularDiscountHandler()no_discount_handler = NoDiscountHandler()# 设置处理者顺序vip_handler.set_successor(regular_handler)regular_handler.set_successor(no_discount_handler)# 发送请求vip_handler.apply_discount(user1, 100)vip_handler.apply_discount(user2, 100)vip_handler.apply_discount(user3, 100)

这个示例模拟了一个用户购买商品时根据其会员等级获得不同折扣的场景。根据用户是否是 VIP 会员或普通会员,处理者会决定是否给予折扣,如果不符合条件,则没有折扣。


使用职责链设计模式时,需要注意哪些地方?

在使用职责链设计模式时,需要注意以下几个方面:

  1. 链的构建: 确保正确构建处理者链。每个处理者都应该知道其后继者是谁,以便请求可以沿着链传递。

  2. 避免循环链: 确保链不会形成循环,否则可能导致请求陷入无限循环,影响系统性能。

  3. 请求的处理: 每个处理者应该明确自己能够处理的请求类型和条件,确保不同处理者之间的处理逻辑不重叠或冲突。

  4. 适当的终止条件: 确保有适当的终止条件。如果没有一个处理者能够处理请求,需要有默认处理或者终止请求的处理方式。

  5. 灵活性与可扩展性: 职责链模式的灵活性是其优势之一,但也要确保链条的灵活性不会影响到代码的维护和扩展。

  6. 性能考虑: 过长的处理者链可能会影响性能,因为每个请求需要在整个链条上进行传递和寻找处理者。在设计时需权衡灵活性与性能。

  7. 单一职责原则: 每个处理者最好只负责一种类型的请求,遵循单一职责原则。

  8. 清晰的责任划分: 处理者的责任应该清晰,每个处理者的作用和职责应该被明确定义,以避免混乱和不必要的复杂性。

综上所述,使用职责链模式时需注意合理构建链条、避免循环、定义清晰的终止条件和责任划分,以确保系统的正确性、可维护性和扩展性。


本文就到这里了,感谢您的阅读 。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇

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

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

相关文章

IDEA插件推荐:Apipost-Helper

Hello&#xff0c;大家好&#xff0c;我是灰小猿。 今天分享一下我最近在开发过程中发现的一个比较实用的IDEA插件—Apipost-Helper IDEA虽然能够帮助开发人员更加高效地编写、调试和部署软件应用程序。但我们在编写完接口代码后肯定还需要进行接口调试等操作&#xff0c;这个…

国际知名商学院复旦大学EMBA荣登全球第8位,中文项目国内居首

2023年10月16日&#xff0c;英国《金融时报》&#xff08;FT&#xff09;发布全球EMBA项目排名。复旦大学EMBA位列全球8强&#xff0c;蝉联中文项目全球第一。学术研究、生源资历、商学院顾问委员会国际化程度、整体满意度等数个重要指标位列中文项目全球第 1位。    排名不…

apply和call在Javascript中的使用与区别

apply和call在js中的使用与区别&#xff1a; 字符串格式化&#xff1a; ${占位符} name小帅 console.log(我是${name}) //我是小帅apply: 语法&#xff1a;function.apply(thisArg, [argsArray])thisArg&#xff1a;可选参数&#xff0c;指定函数执行时的上下文&#xff08…

Bootloader——预编程流程

预编程目录 前言一、预编程步骤1.1 切换到扩展会话1.2 检查刷写前提条件整车ECU进入扩展会话(补充)1.3 停用故障码存储功能1.4 停止通信(一般报文或网络管理报文)前言 刷写过程定义了刷写前、刷写中、刷写后三个阶段。 一、预编程步骤 预编程步骤用来做刷写前的CAN网络准…

公共字段自动填充-@TableField的fill实现(2)

TheadLocal 客户端发送的每次http请求&#xff0c;在服务端都会分配新的线程。因此登录检查过滤器、controller、元数据对象处理器属于一个线程。 TheadLocal是线程的局部变量&#xff1a; TheadLocal常用方法&#xff1a; 如何在元数据对象处理器中获取当前登录用户的id&…

二十、虚拟机网络配置

1、Linux网络配置原理 我自己Linux虚拟机的IP地址是&#xff1a;192.168.159.131 vmnet8&#xff1a;192.168.159.1 无线网卡&#xff1a;192.168.159.1 2、查看网络IP和网关 查看虚拟网络编辑器和修改IP地址 如果把这个位置的子网IP换成&#xff1a;192.168.8.0的话重启虚拟机…

【开源】基于Vue.js的在线课程教学系统的设计和实现

项目编号&#xff1a; S 014 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S014&#xff0c;文末获取源码。} 项目编号&#xff1a;S014&#xff0c;文末获取源码。 目录 一、摘要1.1 系统介绍1.2 项目录屏 二、研究内容2.1 课程类型管理模块2.2 课程管理模块2…

数字IC前端学习笔记:异步复位,同步释放

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 异步复位 异步复位是一种常见的复位方式&#xff0c;可以使电路进入一个可知的状态。但是不正确地使用异步复位会导致出现意想不到的错误&#xff0c;复位释放便是…

力扣hot100 两数之和 哈希表

&#x1f468;‍&#x1f3eb; 力扣 两数之和 &#x1f60b; 思路 在一个数组中如何快速找到某一个数的互补数&#xff1a;哈希表 O(1)实现⭐ AC code class Solution {public int[] twoSum(int[] nums, int target){HashMap<Integer, Integer> map new HashMap<&g…

安卓源码-工程目录

1、程序启动配置及主要的权限声明 2、 界面渲染 3、 布局用 4、 常量等 5、 gradle构建

【Linux】C文件系统详解(三)——如何理解缓冲区以及自主封装一个文件接口

文章目录 如何理解缓冲区现象概念:文件缓冲区为什么要有缓冲区缓冲区在哪里 自己封装一个简单的文件接口自主封装目标 代码关于缓冲区强制刷新内核 关于字符串格式化函数printf和scanf函数 如何理解缓冲区 以前写过一个进度条, 有一个输出缓冲区->这个缓冲区在哪里,为什么要…

python中列表的基础解释

列表&#xff1a; 一种可以存放多种类型数据的数据结构 列表的创建&#xff1a; 1.用【】创建列表 #创建一个空列表 list1[] #创建一个非空列表 list2 [zhang,li,ying,1,2,3] #输出内容及类型 print(list1,type(list1)) print(list2,type(list2))结果&#xff1a; 2.使用list…