python chain of responsibility

Solutions on MaxInterview for python chain of responsibility by the best coders in the world

showing results for - "python chain of responsibility"
Sirine
18 Jun 2018
1from __future__ import annotations
2from abc import ABC, abstractmethod
3from typing import Any, Optional
4
5
6class Handler(ABC):
7    """
8    The Handler interface declares a method for building the chain of handlers.
9    It also declares a method for executing a request.
10    """
11
12    @abstractmethod
13    def set_next(self, handler: Handler) -> Handler:
14        pass
15
16    @abstractmethod
17    def handle(self, request) -> Optional[str]:
18        pass
19
20
21class AbstractHandler(Handler):
22    """
23    The default chaining behavior can be implemented inside a base handler
24    class.
25    """
26
27    _next_handler: Handler = None
28
29    def set_next(self, handler: Handler) -> Handler:
30        self._next_handler = handler
31        # Returning a handler from here will let us link handlers in a
32        # convenient way like this:
33        # monkey.set_next(squirrel).set_next(dog)
34        return handler
35
36    @abstractmethod
37    def handle(self, request: Any) -> str:
38        if self._next_handler:
39            return self._next_handler.handle(request)
40
41        return None
42
43
44"""
45All Concrete Handlers either handle a request or pass it to the next handler in
46the chain.
47"""
48
49
50class MonkeyHandler(AbstractHandler):
51    def handle(self, request: Any) -> str:
52        if request == "Banana":
53            return f"Monkey: I'll eat the {request}"
54        else:
55            return super().handle(request)
56
57
58class SquirrelHandler(AbstractHandler):
59    def handle(self, request: Any) -> str:
60        if request == "Nut":
61            return f"Squirrel: I'll eat the {request}"
62        else:
63            return super().handle(request)
64
65
66class DogHandler(AbstractHandler):
67    def handle(self, request: Any) -> str:
68        if request == "MeatBall":
69            return f"Dog: I'll eat the {request}"
70        else:
71            return super().handle(request)
72
73
74def client_code(handler: Handler) -> None:
75    """
76    The client code is usually suited to work with a single handler. In most
77    cases, it is not even aware that the handler is part of a chain.
78    """
79
80    for food in ["Nut", "Banana", "Cup of coffee"]:
81        print(f"\nClient: Who wants a {food}?")
82        result = handler.handle(food)
83        if result:
84            print(f"  {result}", end="")
85        else:
86            print(f"  {food} was left untouched.", end="")
87
88
89if __name__ == "__main__":
90    monkey = MonkeyHandler()
91    squirrel = SquirrelHandler()
92    dog = DogHandler()
93
94    monkey.set_next(squirrel).set_next(dog)
95
96    # The client should be able to send a request to any handler, not just the
97    # first one in the chain.
98    print("Chain: Monkey > Squirrel > Dog")
99    client_code(monkey)
100    print("\n")
101
102    print("Subchain: Squirrel > Dog")
103    client_code(squirrel)