Nội dung
Builder là một mẫu thiết kế khởi tạo, cho phép xây dựng các đối tượng phức tạp theo từng bước.
Không giống như các mẫu khởi tạo khác, Builder không yêu cầu các sản phẩm phải có giao diện chung. Điều đó làm cho nó có thể tạo các sản phẩm khác nhau bằng cách sử dụng cùng một quy trình xây dựng.
Sử dụng mẫu trong Python
Sử dụng: Mẫu Builder là một mẫu nổi tiếng trong Python. Nó đặc biệt hữu ích khi bạn cần tạo một đối tượng với nhiều tùy chọn cấu hình khả thi.
Nhận biết: Mẫu Builder có thể được nhận dạng trong một lớp, lớp này có một phương thức tạo duy nhất và một số phương thức để cấu hình đối tượng kết quả. Các phương thức Builder thường hỗ trợ chuỗi (ví dụ: someBuilder.setValueA(1).setValueB(2).create()).
Chương trình minh họa
Ví dụ này minh họa cấu trúc của mẫu thiết kế Builder. Nó tập trung vào việc trả lời những câu hỏi sau:
- Nó bao gồm những lớp nào?
- Các lớp này có vai trò gì?
- Các thành phần của mẫu có liên quan với nhau theo cách nào?
main.py
from __future__ import annotations
from abc import ABC, abstractmethod, abstractproperty
from typing import Any
class Builder(ABC):
"""
Giao diện Builder chỉ định các phương thức để tạo các phần khác nhau
của đối tượng sản phẩm.
"""
@abstractproperty
def product(self) -> None:
pass
@abstractmethod
def produce_part_a(self) -> None:
pass
@abstractmethod
def produce_part_b(self) -> None:
pass
@abstractmethod
def produce_part_c(self) -> None:
pass
class ConcreteBuilder1(Builder):
"""
Các lớp Concrete Builder tuân theo giao diện Builder và cung cấp các triển khai
cụ thể của các bước xây dựng. Chương trình của bạn có thể có một số biến
thể của Builder, được triển khai khác nhau.
"""
def __init__(self) -> None:
"""
Một thể hiện builder mới phải chứa một đối tượng sản phẩm trống, được
sử dụng trong quá trình lắp ráp tiếp theo.
"""
self.reset()
def reset(self) -> None:
self._product = Product1()
@property
def product(self) -> Product1:
"""
Các Concrete Builder phải cung cấp các phương pháp của riêng họ để lấy kết
quả. Đó là bởi vì nhiều kiểu builder khác nhau có thể tạo ra các sản phẩm hoàn
toàn khác nhau không tuân theo cùng một giao diện. Do đó, các phương thức
như vậy không thể được khai báo trong giao diện Builder cơ sở.
Thông thường, sau khi trả lại kết quả cuối cùng cho client, một builder dự kiến
sẽ sẵn sàng để bắt đầu tạo một sản phẩm khác. Đó là lý do tại sao thường gọi
phương thức reset ở cuối thân phương thức getProduct. Tuy nhiên, việc này
là không bắt buộc và bạn có thể để các builder đợi lệnh gọi reset tường minh
từ client trước khi loại bỏ kết quả trước đó.
"""
product = self._product
self.reset()
return product
def produce_part_a(self) -> None:
self._product.add("PartA1")
def produce_part_b(self) -> None:
self._product.add("PartB1")
def produce_part_c(self) -> None:
self._product.add("PartC1")
class Product1():
"""
Chỉ nên sử dụng mẫu Builder khi sản phẩm của bạn khá phức tạp
và yêu cầu cấu hình có thể mở rộng.
Không giống như trong các mẫu khởi tạo khác, các builder khác nhau có thể tạo ra
các sản phẩm không liên quan. Nói cách khác, kết quả của các builder khác nhau
có thể không phải lúc nào cũng tuân theo cùng một giao diện.
"""
def __init__(self) -> None:
self.parts = []
def add(self, part: Any) -> None:
self.parts.append(part)
def list_parts(self) -> None:
print(f"Product parts: {', '.join(self.parts)}", end="")
class Director:
"""
Director chỉ chịu trách nhiệm thực hiện các bước xây dựng theo một trình tự cụ
thể. Nó rất hữu ích khi sản xuất sản phẩm theo trật tự hoặc cấu hình cụ thể.
Nói một cách chính xác, lớp Director là tùy chọn, vì client có thể kiểm soát
trực tiếp các builder.
"""
def __init__(self) -> None:
self._builder = None
@property
def builder(self) -> Builder:
return self._builder
@builder.setter
def builder(self, builder: Builder) -> None:
"""
Director làm việc với bất kỳ thể hiện builder nào mà client truyền đến nó.
Bằng cách này, client có thể thay đổi kiểu cuối cùng của sản phẩm
mới được lắp ráp.
"""
self._builder = builder
"""
Director có thể xây dựng một số biến thể sản phẩm bằng các
bước xây dựng giống nhau.
"""
def build_minimal_viable_product(self) -> None:
self.builder.produce_part_a()
def build_full_featured_product(self) -> None:
self.builder.produce_part_a()
self.builder.produce_part_b()
self.builder.produce_part_c()
if __name__ == "__main__":
"""
Client tạo một đối tượng builder, chuyển nó cho director và sau đó bắt đầu
quá trình xây dựng. Kết quả cuối cùng được truy xuất từ đối tượng builder.
"""
director = Director()
builder = ConcreteBuilder1()
director.builder = builder
print("Standard basic product: ")
director.build_minimal_viable_product()
builder.product.list_parts()
print("\n")
print("Standard full featured product: ")
director.build_full_featured_product()
builder.product.list_parts()
print("\n")
# Hãy nhớ rằng, mẫu Builder có thể được sử dụng mà không có lớp Director.
print("Custom product: ")
builder.produce_part_a()
builder.produce_part_b()
builder.product.list_parts()
Kết quả:
Standard basic product:
Product parts: PartA1
Standard full featured product:
Product parts: PartA1, PartB1, PartC1
Custom product:
Product parts: PartA1, PartC1
Để lại một bình luận