-
Notifications
You must be signed in to change notification settings - Fork 0
/
ChainOfResponsibilityDP.py
103 lines (77 loc) · 2.66 KB
/
ChainOfResponsibilityDP.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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)