Nội dung
Composite là một mẫu thiết kế cấu trúc cho phép sắp xếp các đối tượng thành một cấu trúc giống như cây và làm việc với nó như thể nó là một đối tượng đơn lẻ.
Composite đã trở thành một giải pháp khá phổ biến cho hầu hết các vấn đề yêu cầu xây dựng cấu trúc cây. Tính năng tuyệt vời của Composite là khả năng chạy các phương thức đệ quy trên toàn bộ cấu trúc cây và tổng hợp kết quả.
Cách sử dụng mẫu
Cách sử dụng: Mẫu Composite khá phổ biến trong Python. Nó thường được sử dụng để biểu thị thứ bậc của các thành phần giao diện người dùng hoặc chương trình hoạt động với đồ thị.
Nhận dạng: Nếu bạn có cây đối tượng và mỗi đối tượng của cây là một phần của cùng một hệ thống phân cấp lớp, thì đây rất có thể là một composite. Nếu các phương thức của các lớp này ủy thác công việc cho các đối tượng con của cây và thực hiện nó thông qua lớp cơ sở / giao diện của hệ thống phân cấp, thì đây chắc chắn là một composite.
Chương trình mẫu
main.py
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import List
class Component(ABC):
"""
Lớp cơ sở Component khai báo các hoạt động chung cho cả các đối tượng
đơn giản và phức tạp của một composition.
"""
@property
def parent(self) -> Component:
return self._parent
@parent.setter
def parent(self, parent: Component):
"""
Tùy chọn, Component cơ sở có thể khai báo một giao diện để thiết lập và
truy cập thành phần cha trong cấu trúc cây. Nó cũng có thể cung cấp
một số triển khai mặc định cho các phương thức này.
"""
self._parent = parent
"""
Trong một số trường hợp, sẽ có lợi nếu xác định các hoạt động quản lý lớp
con ngay trong lớp Component. Bằng cách này, bạn sẽ không cần hiển thị
bất kỳ lớp component cụ thể nào với client, ngay cả trong quá trình tạo cây
đối tượng. Nhược điểm là các phương thức này sẽ rỗng đối với các nút leaf.
"""
def add(self, component: Component) -> None:
pass
def remove(self, component: Component) -> None:
pass
def is_composite(self) -> bool:
"""
You can provide a method that lets the client code figure out whether a
component can bear children.
"""
return False
@abstractmethod
def operation(self) -> str:
"""
Có thể cung cấp một phương thức cho phép client xác định liệu một
component có nút con hay không.
"""
pass
class Leaf(Component):
"""
Lớp Lá (Leaf) đại diện cho các đối tượng cuối cùng của một cây.
Một nút lá không thể có con.
Thông thường, các đối tượng Leaf thực hiện công việc thực tế, trong khi các
đối tượng Composite chỉ ủy quyền cho các thành phần con của chúng.
"""
def operation(self) -> str:
return "Leaf"
class Composite(Component):
"""
Lớp Composite đại diện cho các thành phần phức tạp có thể có con. Thông
thường, các đối tượng Composite ủy thác công việc thực tế cho con cái của
chúng và sau đó "tổng hợp" kết quả.
"""
def __init__(self) -> None:
self._children: List[Component] = []
"""
Một đối tượng Composite có thể thêm hoặc bớt các thành phần khác (cả
đơn giản hoặc phức tạp) vào hoặc khỏi danh sách con của nó.
"""
def add(self, component: Component) -> None:
self._children.append(component)
component.parent = self
def remove(self, component: Component) -> None:
self._children.remove(component)
component.parent = None
def is_composite(self) -> bool:
return True
def operation(self) -> str:
"""
Composite thực thi logic chính của nó theo một cách cụ thể. Nó duyệt đệ
quy qua tất cả các con của nó, thu thập và tổng hợp kết quả của chúng.
Vì các con của composite truyền những lệnh gọi này cho con của chúng
và cứ thế, kết quả là toàn bộ cây đối tượng được duyệt qua.
"""
results = []
for child in self._children:
results.append(child.operation())
return f"Branch({'+'.join(results)})"
def client_code(component: Component) -> None:
"""
Client hoạt động với tất cả các component thông qua giao diện cơ sở.
"""
print(f"RESULT: {component.operation()}", end="")
def client_code2(component1: Component, component2: Component) -> None:
"""
Nhờ các hoạt động quản lý lớp con được khai báo trong lớp Component cơ sở,
client có thể hoạt động với bất kỳ thành phần nào, đơn giản hay phức tạp mà
không phụ thuộc vào các lớp cụ thể của chúng.
"""
if component1.is_composite():
component1.add(component2)
print(f"RESULT: {component1.operation()}", end="")
if __name__ == "__main__":
# Bằng cách này, client có thể hỗ trợ các thành phần lá đơn giản...
simple = Leaf()
print("Client: I've got a simple component:")
client_code(simple)
print("\n")
# ...cũng như các thành phần phức tạp.
tree = Composite()
branch1 = Composite()
branch1.add(Leaf())
branch1.add(Leaf())
branch2 = Composite()
branch2.add(Leaf())
tree.add(branch1)
tree.add(branch2)
print("Client: Now I've got a composite tree:")
client_code(tree)
print("\n")
print("Client: I don't need to check the components classes even when managing the tree:")
client_code2(tree, simple)
Kết quả
Client: I've got a simple component:
RESULT: Leaf
Client: Now I've got a composite tree:
RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf))
Client: I don't need to check the components classes even when managing the tree:
RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)
Để lại một bình luận