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

news2024/11/17 7:25:25

什么是职责链(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 = successor

    def set_successor(self, successor):
        self.successor = successor

    @abstractmethod
    def 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 = successor

    def set_successor(self, successor):
        self.successor = successor

    @abstractmethod
    def 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.coloradmin.cn/o/1226822.html

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

相关文章

基于stm32移植使用u8g2 库

前言 前面我已经写了如何使用stm32 使用软件IIC的方法驱动OLED&#xff0c;但是其实我们可以有更简单的使用方法&#xff0c;对于SSD1306 这款OLED 显示屏来说&#xff0c;其实已经有开源库可以直接使用了&#xff0c;我们只需要将对应的库移植过来&#xff0c;做一些简单的修改…

单片机课程设计——基于C51电子密码锁(源代码)

本设计是基于AT89C51单片机的电子密码锁设计&#xff0c;实现电子密码锁的基本功能。我们这里实现的是硬件仿真&#xff0c;关于软件仿真可以参考其他人的文章。 单片机课程设计--基于C51电子密码锁 效果展示 我们先来看效果展示&#xff0c;公主王子请看视频&#xff1a; 课…

【Spring总结】注解开发

本篇讲的内容主要是基于Spring v2.5的注解来完成bean的定义 之前都是使用纯配置的方式来定义的bean 文章目录 前言1. Spring v2.5 注解开发定义bean第一步&#xff1a;在需要定义的类上写上注解Component第二步&#xff1a;在Spring Config中定义扫描包第三步&#xff1a;主方法…

java springboot 在测试类中声明临时Bean对象

上文 java springboot在当前测试类中添加临时属性 不影响application和其他范围 中 我们讲了怎么在测试类中设置临时属性 但是 如果我们想设置临时的Bean呢&#xff1f; 其实做过几个项目的人都会理解 我们很多功能 需要一些第三方bean才能完成 那么 我们可能存在需要用第三方b…

图书管理系统(图文详解,附源码)

前言&#xff1a;本文旨在用面向对象的思想编程实现图书管理系统&#xff0c;功能包括增删查找&#xff0c;完整源码放在文末&#xff0c;大家有需自取 目录 一.整体框架 二.书籍和书架 书籍(Book) 书架(BookRack) 三.对书籍的相关操作 操作接口(IOperation) 新增图书(A…

项目点使用Redis作为缓存技术-自用

在spring boot项目中&#xff0c;使用缓存技术只需在项目中导入相关缓存技术的依赖包&#xff0c;并在启动类上使用EnableCaching开启缓存支持即可。 例如&#xff0c;使用Redis作为缓存技术&#xff0c;只需要导入Spring data Redis的maven坐标即可。 描述 使用Redis缓存高频数…

WSA子系统(一)

WSA子系统安装教程 Windows Subsystem for Android (WSA) 是微软推出的一项功能&#xff0c;它允许用户在 Windows 11 上运行 Android 应用程序。通过在 Windows 11 上引入 WSA&#xff0c;用户可以在其 PC 上轻松运行 Android 应用程序&#xff0c;从而扩展了用户的应用程序选…

RobotFramework之用例执行时添加命令行参数(十三)

学习目录 引言 标签tag 设置变量 随机执行顺序 设置监听器 输出日志目录和文件 引言 Robot Framework 提供了许多命令行选项&#xff0c;可用于控制测试用例的执行方式以及生成的输出。本节介绍一些常用的选项语法。 标签tag 之前文章我们介绍过&#xff0c;在测试套件…

Leetcode经典题目之“双指针交换元素“类题目

1 LC 27. 移除元素 class Solution {public int removeElement(int[] nums, int val) {int nnums.length;int s0;for(int i0;i<n;i){// 只有不等于目标值的时候才会进行交换&#xff0c;然后移动s指针if(nums[i]!val){swap(nums,i,s);}}return s;}void swap(int[]nums, int…

(数据结构)算法的时间复杂度

注意语句频度和时间复杂度的区别&#xff0c;语句频度是指语句执行的次数&#xff0c;不可以像时间复杂度一样近似次数和省略常数项

在线识别二维码工具

具体请前往&#xff1a;在线二维码识别解码工具--在线识别并解码二维码网址等内容

FlinkCDC数据实时同步Mysql到ES

考大家一个问题&#xff0c;如果想要把数据库的数据同步到别的地方,比如es,mongodb,大家会采用哪些方案呢&#xff1f; ::: 定时扫描同步&#xff1f; 实时日志同步? 定时同步是一个很好的方案&#xff0c;比较简单&#xff0c;但是如果对实时要求比较高的话&#xff0c;定…

HFSS螺旋线圈的设计与仿真

HFSS螺旋线圈的设计与仿真 HFSS中设计螺旋线圈的方法&#xff1a;参考文献&#xff1a; HFSS中设计螺旋线圈的方法&#xff1a; 打开软件Ansys Eletronics Desktop 2022 R1&#xff0c; 建立工程&#xff0c; File/New 插入HFSS设计&#xff0c; Project/Insert HFSS Design …

【Spring】之初识

未来的几周时间&#xff0c;大概率我会更新一下Spring家族的一些简单知识。而什么是Spring家族&#xff0c;好多同学还不是很清楚&#xff0c;我先来简单介绍一下吧&#xff1a; 所谓Spring家族&#xff0c;它其实就是一个框架&#xff0c;是基于Servlet再次进行封装的内容。为…

大模型的交互能力

摘要&#xff1a; 基础大模型显示出明显的潜力&#xff0c;可以改变AI系统的开发人员和用户体验&#xff1a;基础模型降低了原型设计和构建AI应用程序的难度阈值&#xff0c;因为它们在适应方面的样本效率&#xff0c;并提高了新用户交互的上限&#xff0c;因为它们的多模式和生…

笔记55:长短期记忆网络 LSTM

本地笔记地址&#xff1a;D:\work_file\DeepLearning_Learning\03_个人笔记\3.循环神经网络\第9章&#xff1a;动手学深度学习~现代循环神经网络 a a a a a a a a a

jbase打印完善

上一篇实现了粗略的打印元素绘制协议&#xff0c;并且写了打印示例和导出示例&#xff0c;趁着空隙时间完善一下打印。 首先元素构造函数默认初始化每个字段值 package LIS.Core.Dto;/*** 打印约定元素*/ public class PrintElement {/*** 元素类型*/public String PrintType…

OpenCV快速入门:图像形态学操作

文章目录 前言一、图像形态学基础1.1 背景介绍1.2 像素距离1.2.1 什么是像素距离&#xff1f;1.2.2 常见的像素距离度量方法1.2.3 计算像素距离的代码实现 1.3 图像连通性1.3.1 什么是图像连通性&#xff1f;1.3.2 连通类型1.3.3 连通组件标记1.3.4 连通性在图像处理中的应用 1…

2023.11.18 每日一题(AI自生成应用)【C++】【Python】【Java】【Go】 动态时间序列分析

目录 一、编程挑战&#xff1a;动态时间序列分析 实际应用&#xff1a; 实现提示&#xff1a; 二、实现 1. C 2. Python 3. JAVA 4. Go 一、编程挑战&#xff1a;动态时间序列分析 问题描述&#xff1a; 假设你是一名软件工程师&#xff0c;需要开发一个应用来分析和预…

内容运营策略:个性化推荐

一、推荐系统流程 典型的推荐系统包括3个部分&#xff0c;即召回层&#xff08; Recall )、排序层&#xff08; Rank )和重排层&#xff08; ReRank )。 1&#xff0e;召回层&#xff08; Recall ) 召回层主要是从全量库中首先获取用户可能感兴趣的候选集&#xff0c;是推荐系…