【python设计模式】22、责任链模式

news/2024/7/7 18:54:51

        责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。这种模式建议让请求的发送者和接收者形成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

哲学思想:

         责任链模式的哲学思想是“不要把所有的鸡蛋放在一个篮子里”。这种模式的核心思想是将请求发送者和请求处理者解耦,从而使多个对象都有机会处理请求。这种解耦能够提高系统的灵活性和可扩展性。

简介:

        责任链模式是由多个对象组成的一条链。当一个请求发送者发送一个请求时,这个请求会依次经过链中的每一个对象,直到有一个对象处理它为止。每个对象都有处理请求的机会,如果它不能处理请求,就会将请求传递给下一个对象。这种模式的核心是责任链,它将请求和处理请求的对象链接起来,形成一条链。

优点:

  1. 解耦性:责任链模式可以将请求发送者和请求处理者解耦,从而使多个对象都有机会处理请求。这种解耦能够提高系统的灵活性和可扩展性。

  2. 灵活性:责任链模式可以根据需要动态地组织链,并且可以在链中添加或删除处理者。这种灵活性可以使系统更加适应变化。

  3. 可扩展性:责任链模式可以通过添加或删除处理者来扩展系统的功能,从而实现系统的可扩展性。

  4. 简化对象:责任链模式可以将多个对象组合成一个处理链,从而简化对象的结构。这种简化能够提高系统的性能和可维护性。

缺点:

  1. 处理时间:由于请求经过多个对象处理,所以处理时间可能会比较长。这种长时间的处理可能会影响系统的性能。

  2. 难以调试:由于请求经过多个对象处理,所以当出现问题时,很难确定是哪个对象出现了问题。这种难以调试可能会影响系统的可维护性。

  3. 可能会造成循环调用:由于每个对象都有处理请求的机会,所以如果链中的对象没有正确地组织,可能会出现循环调用,从而导致系统的死循环。

实际应用场景:

  1. 请求处理:在应用程序中,可能需要将请求按照特定的顺序传递给多个处理程序。责任链模式可以使得这些请求能够被有效的处理。

  2. 错误处理:在程序中,可能会发生多种类型的错误。责任链模式可以将这些错误按照一定的优先级进行处理,确保每个错误都能够被正确的处理。

  3. 身份验证:在许多应用程序中,需要对用户进行身份验证。责任链模式可以将身份验证请求传递给多个身份验证程序,以确保请求被正确的处理。

  4. 安全检查:在应用程序中,需要对用户的请求进行安全检查。责任链模式可以将安全检查请求传递给多个安全检查程序,以确保请求被正确的处理。

  5. 日志记录:在应用程序中,需要对操作进行日志记录。责任链模式可以将日志记录请求传递给多个日志记录程序,以确保请求被正确的处理。

python代码实现:

class Handler:
    def __init__(self, successor=None):
        self._successor = successor

    def handle_request(self, request):
        handled = self._handle(request)
        if not handled:
            self._successor.handle_request(request)

    def _handle(self, request):
        raise NotImplementedError('Must provide implementation in subclass.')

class ConcreteHandler1(Handler):
    def _handle(self, request):
        if 0 < request <= 10:
            print(f'Request {request} handled in handler 1')
            return True

class ConcreteHandler2(Handler):
    def _handle(self, request):
        if 10 < request <= 20:
            print(f'Request {request} handled in handler 2')
            return True

class ConcreteHandler3(Handler):
    def _handle(self, request):
        if 20 < request <= 30:
            print(f'Request {request} handled in handler 3')
            return True

class DefaultHandler(Handler):
    def _handle(self, request):
        print(f'End of chain, no handler for {request}')
        return True

class Client:
    def __init__(self):
        self.handler = ConcreteHandler1(ConcreteHandler2(ConcreteHandler3(DefaultHandler())))

    def delegate(self, requests):
        for request in requests:
            self.handler.handle_request(request)

client = Client()
requests = [2, 5, 14, 22, 18, 3, 35, 27, 20]
client.delegate(requests)

        上述代码中,我们定义了一个 Handler 基类,所有具体的处理程序类都应该继承自该类。在基类中,我们定义了一个 handle_request 方法来处理传入的请求。如果当前处理程序可以处理请求,则处理它,否则将请求传递给下一个处理程序。在具体的处理程序子类中,我们重写了 _handle 方法,根据请求的值来确定是否可以处理它。

        我们还定义了一个 DefaultHandler 类,它是一个具体的处理程序类,它将处理链的末尾标志为默认处理程序。最后,我们定义了一个 Client 类,它包含一个具体的处理程序对象,可以委托给该对象来处理传入的请求。

        我们可以创建一个客户端对象,并传递一组请求来测试该代码。在上述示例中,我们传递了一组请求 [2, 5, 14, 22, 18, 3, 35, 27, 20],并使用 delegate 方法将这些请求委托给处理程序。运行代码后,输出结果如下:

Request 2 handled in handler 1
Request 5 handled in handler 1
Request 14 handled in handler 2
Request 22 handled in handler 3
Request 18 handled in handler 2
Request 3 handled in handler 1
End of chain, no handler for 35
Request 27 handled in handler 3
Request 20 handled in handler 2

代码解释:

在以上代码中,Handler 是抽象处理器,定义了处理请求的基本行为和指向下一个处理器的指针。ConcreteHandler1、ConcreteHandler2 和 ConcreteHandler3 是具体处理器,实现了自己的处理逻辑,并根据自己的条件来决定是否处理该请求。DefaultHandler 是默认处理器,用于处理最后一个处理器无法处理的请求。

Client 是客户端,创建了一个处理器链,并将一系列请求委派给处理器链。

具体来说,以上代码的执行流程如下:

  1. Client 创建了一个处理器链:ConcreteHandler1(ConcreteHandler2(ConcreteHandler3(DefaultHandler())))。

  2. Client 将一系列请求 [2, 5, 14, 22, 18, 3, 35, 27, 20] 委派给处理器链。

  3. 处理器链开始处理请求。首先,ConcreteHandler1 尝试处理请求 2,但由于该请求不在它的处理范围内,它将请求传递给下一个处理器 ConcreteHandler2。

  4. ConcreteHandler2 尝试处理请求 2,但仍然无法处理,于是将请求传递给下一个处理器 ConcreteHandler3。

  5. ConcreteHandler3 尝试处理请求 2,同样无法处理,于是将请求传递给下一个处理器 DefaultHandler。

  6. DefaultHandler 处理请求 2,并输出日志:"End of chain, no handler for 2"。

  7. 处理器链继续处理请求。ConcreteHandler1 尝试处理请求 5,成功处理,并输出日志:"Request 5 handled in handler 1"。

  8. ConcreteHandler1 继续处理请求 14,但由于该请求不在它的处理范围内,它将请求传递给下一个处理器 ConcreteHandler2。

  9. ConcreteHandler2 成功处理请求 14,并输出日志:"Request 14 handled in handler 2"。

  10. ConcreteHandler2 继续处理请求 22,但由于该请求不在它的处理范围内,它将请求传递给下一个处理器 ConcreteHandler3。

  11. ConcreteHandler3 成功处理请求 22,并输出日志:"Request 22 handled in handler 3"。

  12. ConcreteHandler3 继续处理请求 18,但由于该请求不在它的处理范围内,它将请求传递给下一个处理器 DefaultHandler。

  13. DefaultHandler 成功处理请求 18,并输出日志:"End of chain, no handler for 18"。

    以此类推,即可得到最后结果。

ConcreteHandler1(ConcreteHandler2(ConcreteHandler3(DefaultHandler())))

本句代码解释:

具体来说,它使用了装饰器模式(Decorator Pattern)来实现责任链(Chain of Responsibility)模式。

在责任链模式中,每个处理器(Handler)都可以处理一个请求,如果它不能处理这个请求,就把请求传递给下一个处理器,直到有一个处理器能够处理为止。在这个代码片段中,ConcreteHandler1、ConcreteHandler2、ConcreteHandler3、DefaultHandler 都是处理器,它们都继承自同一个 Handler 父类,并且按照一定的顺序组合在一起,形成了一个责任链。

具体来说,这个代码片段的意思是:

  1. DefaultHandler 是最底层的处理器,也就是整个责任链的终点。如果所有的处理器都不能处理请求,那么就会由 DefaultHandler 来处理请求。

  2. ConcreteHandler3 继承自 Handler,并重写了处理请求的方法。如果 ConcreteHandler3 不能处理请求,那么就会将请求传递给它的下一个处理器。

  3. ConcreteHandler2 继承自 ConcreteHandler3,并重写了处理请求的方法。如果 ConcreteHandler2 不能处理请求,那么就会将请求传递给它的下一个处理器,也就是 ConcreteHandler3。

  4. ConcreteHandler1 继承自 ConcreteHandler2,并重写了处理请求的方法。如果 ConcreteHandler1 不能处理请求,那么就会将请求传递给它的下一个处理器,也就是 ConcreteHandler2。

因此,当一个请求到达 ConcreteHandler1 时,它会首先尝试由 ConcreteHandler1 来处理,如果不能处理,则会传递给 ConcreteHandler2,然后是 ConcreteHandler3,最后是 DefaultHandler。


http://lihuaxi.xjx100.cn/news/1021393.html

相关文章

【c语言】二维数组与指针 存储原理

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…

《MySQL是怎样运行的》读书笔记 2:查询优化

十、单表访问方法 MySQL执行查询语句的方式称为访问方法或者访问类型。 1 访问方法 1) const&#xff1a;通过主键或者唯一二级索引列来定位一条记录。 2) ref&#xff1a;搜索条件为二级索引列与常数进行等值比较&#xff0c;形成的扫描区间为单点扫描区间&#xff0c;采用…

你搞清楚了吗?| GET请求方式的长度限制到底是多少?

目录 &#x1f4cd; 浏览器限制 &#x1f4cd; 服务器限制 在大多数人的一贯认识中&#xff0c;一直认为get请求方式有2048B的长度限制&#xff0c;其实这种说法是有失偏颇的&#xff0c;甚至可以说是错误的。 这个问题一直以来似乎是被N多人误解&#xff0c;其实Http Get方…

P4070 [SDOI2016]生成魔咒(后缀自动机 len数组的含义)

[SDOI2016]生成魔咒 题目描述 魔咒串由许多魔咒字符组成&#xff0c;魔咒字符可以用数字表示。例如可以将魔咒字符 1,21,21,2 拼凑起来形成一个魔咒串 [1,2][1,2][1,2]。 一个魔咒串 SSS 的非空字串被称为魔咒串 SSS 的生成魔咒。 例如 S[1,2,1]S[1,2,1]S[1,2,1] 时&#x…

大中华区艾菲携手阿里妈妈,推动全域科学经营,助力品牌实现确定性增长 | 数据猿专访...

‍数据智能产业创新服务媒体——聚焦数智 改变商业早在2016年底&#xff0c;阿里妈妈提出了全域营销&#xff0c;这是一个数智驱动、以消费者为中心的数智化营销方法论。而让整个营销行业颇为关注的是&#xff0c;全域营销开创的是品牌“以消费者为中心”的数智化营销&#xf…

【微信小程序】初识微信小程序组件

作者简介&#xff1a;一名C站萌新&#xff0c;前来进行小程序的前进之路博主主页&#xff1a;大熊李子&#x1f43b; 一、组件的创建与引用 1.1 创建组件 在项目的根目录中&#xff0c;鼠标右键&#xff0c;创建 components -> test 文件夹在新建的 components -> test…

metaRTC新版本重构ICE全面兼容ICE协议

概述 metaRTC支持P2P的ICE不完善&#xff0c;老版本只实现了stun和turn&#xff0c;缺乏交互式连接实现&#xff0c;新版本重构ICE部分&#xff0c;实现了交互式连接&#xff0c;全面兼容ICE-FULL/ICE_LITE规范。 metaRTC ICE 流程 收集候选地址(Candidate) 通信前先搜集本…

001+limou+2023/2/16+时间空间复杂度

0、数据结构的学习推荐书籍 &#xff08;1&#xff09;《小黑的漫画算法》简单看一下 &#xff08;2&#xff09;《大话数据结构》 &#xff08;3&#xff09;《数据结构&#xff08;C语言版&#xff09;》 1、时间复杂度和空间复杂度 &#xff08;1&#xff09;时间复杂度、…