Nội dung
Chain of Responsibility là mẫu thiết kế hành vi cho phép chuyển yêu cầu dọc theo chuỗi các trình xử lý tiềm năng cho đến khi một trong số họ xử lý yêu cầu.
Mẫu cho phép nhiều đối tượng xử lý yêu cầu mà không cần ghép lớp người gửi (sender) với các lớp cụ thể của người nhận (receiver). Chuỗi có thể được tạo động trong thời gian chạy với bất kỳ trình xử lý nào tuân theo giao diện trình xử lý tiêu chuẩn.
Cách sử dụng
Ví dụ sử dụng: Mẫu Chain of Responsibility không phải là xuất hiện thường xuyên trong chương trình Python vì nó chỉ phù hợp khi mã hoạt động với chuỗi đối tượng.
Nhận dạng: Mẫu có thể nhận biết được bằng các phương thức hành vi của một nhóm đối tượng gọi gián tiếp các phương thức giống nhau trong các đối tượng khác, trong khi tất cả các đối tượng tuân theo giao diện chung.
Chương trình mẫu
main.py
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any, Optional
class Handler(ABC):
"""
Giao diện Handler khai báo phương thức để tạo chuỗi các trình
xử lý. Nó cũng khai báo một phương thức để xử lý yêu cầu.
"""
@abstractmethod
def set_next(self, handler: Handler) -> Handler:
pass
@abstractmethod
def handle(self, request) -> Optional[str]:
pass
class AbstractHandler(Handler):
"""
Hành vi mặc định cho chuỗi có thể được thực hiện
bên trong một lớp xử lý cơ sở.
"""
_next_handler: Handler = None
def set_next(self, handler: Handler) -> Handler:
self._next_handler = handler
# Việc trả lại một trình xử lý ở đây sẽ cho phép chúng ta
# liên kết các trình xử lý theo cách thuận tiện như sau:
# 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
"""
Tất cả Trình xử lý cụ thể hoặc xử lý một yêu cầu
hoặc chuyển nó cho cái tiếp theo trong chuỗi.
"""
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:
"""
Client làm việc với một trình xử lý duy nhất. Trong hầu hết các trường
hợp, nó thậm chí không biết rằng trình xử lý là một phần của chuỗi.
"""
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)
# Client có thể gửi yêu cầu tới bất kỳ trình xử lý nào,
# không chỉ trình xử lý đầu tiên trong chuỗi.
print("Chain: Monkey > Squirrel > Dog")
client_code(monkey)
print("\n")
print("Subchain: Squirrel > Dog")
client_code(squirrel)
Kết quả
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.
Để lại một bình luận