春季促销
责任链

Python 责任链模式讲解和代码示例

责任链是一种行为设计模式 允许你将请求沿着处理者链进行发送 直至其中一个处理者对其进行处理

该模式允许多个对象来对请求进行处理 而无需让发送者类与具体接收者类相耦合 链可在运行时由遵循标准处理者接口的任意处理者动态生成

复杂度

流行度

使用示例 责任链模式在 Python 程序中并不常见 因为它仅在代码与对象链打交道时才能发挥作用

识别方法 该模式可通过一组对象的行为方法间接调用其他对象的相同方法来识别 而且所有对象都会遵循相同的接口

概念示例

本例说明了责任链设计模式的结构并重点回答了下面的问题

  • 它由哪些类组成
  • 这些类扮演了哪些角色
  • 模式中的各个元素会以何种方式相互关联

main.py: 概念示例

from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any, Optional


class Handler(ABC):
    """
    The Handler interface declares a method for building the chain of handlers.
    It also declares a method for executing a request.
    """

    @abstractmethod
    def set_next(self, handler: Handler) -> Handler:
        pass

    @abstractmethod
    def handle(self, request) -> Optional[str]:
        pass


class AbstractHandler(Handler):
    """
    The default chaining behavior can be implemented inside a base handler
    class.
    """

    _next_handler: Handler = None

    def set_next(self, handler: Handler) -> Handler:
        self._next_handler = handler
        # Returning a handler from here will let us link handlers in a
        # convenient way like this:
        # monkey.set_next(squirrel).set_next(dog)
        return handler

    @abstractmethod
    def handle(self, request: Any) -> str:
        if self._next_handler:
            return self._next_handler.handle(request)

        return None


"""
All Concrete Handlers either handle a request or pass it to the next handler in
the chain.
"""


class MonkeyHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "Banana":
            return f"Monkey: I'll eat the {request}"
        else:
            return super().handle(request)


class SquirrelHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "Nut":
            return f"Squirrel: I'll eat the {request}"
        else:
            return super().handle(request)


class DogHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "MeatBall":
            return f"Dog: I'll eat the {request}"
        else:
            return super().handle(request)


def client_code(handler: Handler) -> None:
    """
    The client code is usually suited to work with a single handler. In most
    cases, it is not even aware that the handler is part of a chain.
    """

    for food in ["Nut", "Banana", "Cup of coffee"]:
        print(f"\nClient: Who wants a {food}?")
        result = handler.handle(food)
        if result:
            print(f"  {result}", end="")
        else:
            print(f"  {food} was left untouched.", end="")


if __name__ == "__main__":
    monkey = MonkeyHandler()
    squirrel = SquirrelHandler()
    dog = DogHandler()

    monkey.set_next(squirrel).set_next(dog)

    # The client should be able to send a request to any handler, not just the
    # first one in the chain.
    print("Chain: Monkey > Squirrel > Dog")
    client_code(monkey)
    print("\n")

    print("Subchain: Squirrel > Dog")
    client_code(squirrel)

Output.txt: 执行结果

Chain: Monkey > Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut
Client: Who wants a Banana?
  Monkey: I'll eat the Banana
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.

Subchain: Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut
Client: Who wants a Banana?
  Banana was left untouched.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.

责任链在其他编程语言中的实现

C# 责任链模式讲解和代码示例 C++ 责任链模式讲解和代码示例 Go 责任链模式讲解和代码示例 Java 责任链模式讲解和代码示例 PHP 责任链模式讲解和代码示例 Ruby 责任链模式讲解和代码示例 Rust 责任链模式讲解和代码示例 Swift 责任链模式讲解和代码示例 TypeScript 责任链模式讲解和代码示例