close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

Python Design Patterns: Builder

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

Đã đăng vào

trong

,

bởi

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *