봄맞이 세일
책임 연쇄

파이썬으로 작성된 책임 연쇄

책임 연쇄 패턴은 핸들러 중 하나가 요청을 처리할 때까지 핸들러들의 체인​(사슬)​을 따라 요청을 전달할 수 있게 해주는 행동 디자인 패턴입니다.

이 패턴은 발신자 클래스를 수신자들의 구상 클래스들에 연결하지 않고도 여러 객체가 요청을 처리할 수 있도록 합니다. 체인은 표준 핸들러 인터페이스를 따르는 모든 핸들러와 런타임 때 동적으로 구성될 수 있습니다.

복잡도:

인기도:

사용 예시들: 책임 연쇄 패턴은 파이썬 코드에 매우 일반적이며, 당신의 코드가 필터, 이벤터 체인 등과 같은 객체 체인과 함께 작동할 때 특히 유용합니다.

식별: 패턴의 모든 객체는 공통 인터페이스를 따르며, 다른 객체들의 같은 메서드들을 간접적으로 호출하는 한 객체 그룹의 행동 메서드들이 있습니다.

개념적인 예시

이 예시는 책임 연쇄 패턴의 구조를 보여주고 다음 질문에 중점을 둡니다:

  • 패턴은 어떤 클래스들로 구성되어 있나요?
  • 이 클래스들은 어떤 역할을 하나요?
  • 패턴의 요소들은 어떻게 서로 연관되어 있나요?

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로 작성된 책임 연쇄 자바로 작성된 책임 연쇄 PHP로 작성된 책임 연쇄 루비로 작성된 책임 연쇄 러스트로 작성된 책임 연쇄 스위프트로 작성된 책임 연쇄 타입스크립트로 작성된 책임 연쇄