close up photo of programming of codes

codecungnhau.com

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

Python Design patterns: Abstract Factory

Abstract Factory là một mẫu thiết kế khởi tạo, giải quyết vấn đề tạo ra toàn bộ họ sản phẩm mà không chỉ định các lớp cụ thể của chúng.

Abstract Factory định nghĩa một giao diện để tạo tất cả các sản phẩm riêng biệt nhưng để việc tạo sản phẩm thực tế cho các lớp factory cụ thể. Mỗi loại factory tương ứng với một loại sản phẩm nhất định.

Mã client gọi các phương thức khởi tạo của một đối tượng factory thay vì tạo sản phẩm trực tiếp bằng lệnh gọi phương thức khởi tạo (toán tử new). Vì một factory tương ứng với một biến thể sản phẩm duy nhất nên tất cả các sản phẩm của factory đó sẽ tương thích.

Client chỉ hoạt động với các factory và sản phẩm thông qua các giao diện trừu tượng của chúng. Điều này cho phép client hoạt động với mọi biến thể sản phẩm, được tạo bởi đối tượng factory. Bạn chỉ cần tạo một lớp factory cụ thể mới và chuyển nó cho client.

Cách sử dụng mẫu trong Python

Sử dụng: Mẫu Abstract Factory khá phổ biến trong Python. Nhiều framework và thư viện sử dụng nó để cung cấp cách mở rộng và tùy chỉnh các thành phần tiêu chuẩn của chúng.

Nhận biết: Mẫu dễ dàng được nhận ra bằng các phương thức trả về một đối tượng factory. Sau đó, factory được sử dụng để tạo ra các thành phần phụ cụ thể.

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ế Abstract Factory. 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
class AbstractFactory(ABC):
    """
    Giao diện Abstract Factory khai báo một tập hợp các phương thức trả về các sản phẩm trừu 
    tượng khác nhau. Những sản phẩm này được gọi là một họ và có liên quan với nhau theo 
    một chủ đề hoặc khái niệm. Các sản phẩm của một họ thường có thể cộng tác với nhau. 
    Một họ sản phẩm có thể có một số biến thể, nhưng các sản phẩm của biến thể này 
    không tương thích với các sản phẩm của biến thể khác.
    """
    @abstractmethod
    def create_product_a(self) -> AbstractProductA:
        pass
    @abstractmethod
    def create_product_b(self) -> AbstractProductB:
        pass
class ConcreteFactory1(AbstractFactory):
    """
    Các Concrete Factory sản xuất một họ sản phẩm thuộc một biến thể duy nhất. Nhà máy đảm 
    bảo rằng các sản phẩm tạo ra là tương thích. Lưu ý rằng chữ ký của các phương thức của 
    Concrete Factory trả về một sản phẩm trừu tượng (abstract product), trong khi bên trong 
    phương thức, một sản phẩm cụ thể được khởi tạo.
    """
    def create_product_a(self) -> ConcreteProductA1:
        return ConcreteProductA1()
    def create_product_b(self) -> ConcreteProductB1:
        return ConcreteProductB1()
class ConcreteFactory2(AbstractFactory):
    """
    Mỗi Concrete Factory có một biến thể sản phẩm tương ứng.
    """
    def create_product_a(self) -> ConcreteProductA2:
        return ConcreteProductA2()
    def create_product_b(self) -> ConcreteProductB2:
        return ConcreteProductB2()
class AbstractProductA(ABC):
    """
    Mỗi sản phẩm riêng biệt của một họ sản phẩm nên có một giao diên cơ sở.
    Tất cả các biến thể của sản phẩm đều phải hiện thực giao diện này.
    """
    @abstractmethod
    def useful_function_a(self) -> str:
        pass
"""
Concrete Product được tạo ra tương ứng với Concrete Factory.
"""
class ConcreteProductA1(AbstractProductA):
    def useful_function_a(self) -> str:
        return "The result of the product A1."
class ConcreteProductA2(AbstractProductA):
    def useful_function_a(self) -> str:
        return "The result of the product A2."
class AbstractProductB(ABC):
    """
    Đây là giao diện cơ sở của một sản phẩm khác. Tất cả các sản phẩm có thể tương 
    tác với nhau, nhưng chỉ có thể thích hợp tương tác giữa các sản phẩm của cùng 
    một biến thể cụ thể.
    """
    @abstractmethod
    def useful_function_b(self) -> None:
        """
        Sản phẩm B có thể làm mọi thứ của nó...
        """
        pass
    @abstractmethod
    def another_useful_function_b(self, collaborator: AbstractProductA) -> None:
        """
        ...nhưng cũng có thể tương tác với sản phẩm A.
        Abstract Factory đảm bảo rằng tất cả các sản phẩm mà nó tạo ra đều 
        có cùng một biến thể và do đó, tương thích.
        """
        pass
"""
Concrete Product được tạo ra tương ứng bởi Concrete Factory.
"""
class ConcreteProductB1(AbstractProductB):
    def useful_function_b(self) -> str:
        return "The result of the product B1."
    """
    Biến thể, Sản phẩm B1, chỉ có thể hoạt động chính xác với biến thể, Sản phẩm A1. 
    Tuy nhiên, nó chấp nhận bất kỳ thể hiện nào của AbstractProductA làm đối số.
    """
    def another_useful_function_b(self, collaborator: AbstractProductA) -> str:
        result = collaborator.useful_function_a()
        return f"The result of the B1 collaborating with the ({result})"
class ConcreteProductB2(AbstractProductB):
    def useful_function_b(self) -> str:
        return "The result of the product B2."
    def another_useful_function_b(self, collaborator: AbstractProductA):
        """
        Biến thể, Sản phẩm B2, chỉ có thể hoạt động chính xác với biến thể, Sản phẩm A2. 
        Tuy nhiên, nó chấp nhận bất kỳ thể hiện nào của AbstractProductA làm đối số.
        """
        result = collaborator.useful_function_a()
        return f"The result of the B2 collaborating with the ({result})"
def client_code(factory: AbstractFactory) -> None:
    """
    Mã Client chỉ hoạt động với các nhà máy và sản phẩm thông qua các kiểu trừu tượng: 
    AbstractFactory và AbstractProduct. Điều này cho phép bạn truyền bất kỳ lớp con nào 
    của nhà máy hoặc sản phẩm sang mã client mà không làm hỏng nó.
    """
    product_a = factory.create_product_a()
    product_b = factory.create_product_b()
    print(f"{product_b.useful_function_b()}")
    print(f"{product_b.another_useful_function_b(product_a)}", end="")
if __name__ == "__main__":
    """
    Mã Client  có thể hoạt động với bất kỳ lớp Concrete Factory nào.
    """
    print("Client: Testing client code with the first factory type:")
    client_code(ConcreteFactory1())
    print("\n")
    print("Client: Testing the same client code with the second factory type:")
    client_code(ConcreteFactory2())

Kết quả:

Client: Testing client code with the first factory type:
The result of the product B1.
The result of the B1 collaborating with the (The result of the product A1.)
Client: Testing the same client code with the second factory type:
The result of the product B2.
The result of the B2 collaborating with the (The result of the product A2.)

Đã đă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 *