動態工廠模式允許在執行時根據需求建立不同型別的物件,提高了系統的靈活性。搭配依賴注入,可以進一步降低物件之間的耦合度,方便程式碼的測試和維護。工廠方法模式則透過定義一個抽象的工廠介面,讓子類別決定要例項化哪個類別,提供更進一步的彈性。而抽象工廠模式則更進一步,可以建立一系列相關或相互依賴的物件,確保產品的一致性。這些模式都有助於提升程式碼的可讀性、可維護性和可擴充套件性,是軟體開發中常用的設計模式。

動態工廠模式與依賴注入的應用

在軟體開發中,工廠模式是一種常見的設計模式,用於建立物件而無需指定具體類別。動態工廠模式是工廠模式的一種變體,允許在執行時動態地註冊和建立物件。這種模式可以提高系統的可擴充套件性和維護性。

動態工廠模式的實作

以下是一個簡單的動態工廠模式實作:

class DynamicCreator:
    def __init__(self, product_type: str):
        self.product_type = product_type

    def factory_method(self) -> Product:
        if self.product_type in product_registry:
            return product_registry[self.product_type]()
        raise ValueError("Unknown product type")

# 註冊產品
product_registry = {}

def register_product(product_type: str):
    def decorator(cls):
        product_registry[product_type] = cls
        return cls
    return decorator

# 定義產品類別
@register_product("A")
class ConcreteProductDynamicA(Product):
    def perform_operation(self):
        return "Operation from ConcreteProductDynamicA"

@register_product("B")
class ConcreteProductDynamicB(Product):
    def perform_operation(self):
        return "Operation from ConcreteProductDynamicB"

在這個例子中,DynamicCreator 類別負責建立產品物件,而 product_registry 字典則用於儲存已註冊的產品類別。register_product 函式用於註冊新的產品類別。

依賴注入的應用

在複雜的系統中,物件之間的依賴關係可能非常複雜。依賴注入是一種設計模式,用於解耦物件之間的依賴關係。以下是一個簡單的依賴注入實作:

class Service:
    def __init__(self, repository, configuration):
        self.repository = repository

class Repository:
    def fetch(self):
        pass

class ConcreteRepository(Repository):
    def fetch(self):
        return "Data fetched by 玄貓"

def dependency_factory(cls, dependencies: dict):
    instance = cls.__new__(cls)
    for name, dependency in dependencies.items():
        setattr(instance, name, dependency)
    instance.__init__()
    return instance

class DIServiceCreator:
    def __init__(self, service_type: str, dependencies: dict):
        self.service_type = service_type
        self.dependencies = dependencies

    def create_service(self):
        return dependency_factory(self.service_type, self.dependencies)

在這個例子中,Service 類別依賴於 Repository 類別,而 ConcreteRepository 類別則實作了 Repository 介面。dependency_factory 函式用於建立物件並注入依賴項。

什麼是工廠方法模式?

工廠方法模式是一種建立型設計模式,提供了一種方式來建立物件,而無需指定具體的類別。這個模式允許子類別決定要例項化哪個類別,並提供了一種方式來封裝物件的建立邏輯。

工廠方法模式的結構

工廠方法模式由以下幾個部分組成:

  • Product:定義了工廠方法所建立的物件的介面。
  • ConcreteProduct:實作了 Product 介面的具體類別。
  • Creator:定義了工廠方法的介面。
  • ConcreteCreator:實作了 Creator 介面的具體類別,並負責建立 ConcreteProduct 例項。

工廠方法模式的優點

工廠方法模式有以下幾個優點:

  • 封裝性:工廠方法模式封裝了物件的建立邏輯,使得客戶端不需要知道具體的類別。
  • 擴充套件性:工廠方法模式使得新增新的具體類別變得容易,只需要建立新的 ConcreteProduct 和 ConcreteCreator 類別即可。
  • 多型性:工廠方法模式允許客戶端使用相同的介面建立不同的物件。

工廠方法模式的實作

以下是工廠方法模式的一個簡單實作:

from abc import ABC, abstractmethod

# Product
class Service(ABC):
    @abstractmethod
    def perform_service(self):
        pass

# ConcreteProduct
class ConcreteService(Service):
    def perform_service(self):
        print("Performing concrete service")

# Creator
class ServiceCreator(ABC):
    @abstractmethod
    def factory_method(self) -> Service:
        pass

# ConcreteCreator
class ConcreteServiceCreator(ServiceCreator):
    def factory_method(self) -> Service:
        return ConcreteService()

# 客戶端程式碼
creator = ConcreteServiceCreator()
service = creator.factory_method()
service.perform_service()

在這個例子中,Service是 Product,ConcreteService是 ConcreteProduct,ServiceCreator是 Creator,ConcreteServiceCreator是 ConcreteCreator。客戶端程式碼使用ConcreteServiceCreator建立ConcreteService例項,並呼叫其perform_service方法。

工廠方法模式的應用

工廠方法模式可以應用於以下幾種情況:

  • 物件建立複雜:當物件的建立邏輯複雜時,工廠方法模式可以幫助封裝這些邏輯。
  • 需要多型性:當客戶端需要使用相同的介面建立不同的物件時,工廠方法模式可以提供多型性。
  • 需要擴充套件性:當需要新增新的具體類別時,工廠方法模式可以使得新增新的類別變得容易。

結合依賴注入和多執行緒

工廠方法模式可以結合依賴注入和多執行緒來提高系統的可擴充套件性和可維護性。以下是結合依賴注入和多執行緒的例子:

import threading
from abc import ABC, abstractmethod

# Product
class Service(ABC):
    @abstractmethod
    def perform_service(self):
        pass

# ConcreteProduct
class ConcreteService(Service):
    def __init__(self, dependencies):
        self.dependencies = dependencies

    def perform_service(self):
        print("Performing concrete service")

# Creator
class ServiceCreator(ABC):
    @abstractmethod
    def factory_method(self) -> Service:
        pass

# ConcreteCreator
class ConcreteServiceCreator(ServiceCreator):
    def __init__(self, dependencies):
        self.dependencies = dependencies

    def factory_method(self) -> Service:
        return ConcreteService(self.dependencies)

# 客戶端程式碼
class Client:
    def __init__(self, creator):
        self.creator = creator

    def perform_service(self):
        service = self.creator.factory_method()
        service.perform_service()

# 多執行緒
def worker(creator):
    client = Client(creator)
    client.perform_service()

dependencies = {"repository": "repository", "configuration": "configuration"}
creator = ConcreteServiceCreator(dependencies)

threads = []
for i in range(5):
    thread = threading.Thread(target=worker, args=(creator,))
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

在這個例子中,ConcreteService類別接受依賴注入,ConcreteServiceCreator類別負責建立ConcreteService例項。客戶端程式碼使用ConcreteServiceCreator建立ConcreteService例項,並呼叫其perform_service方法。多執行緒被使用來演示工廠方法模式在多執行緒環境下的應用。

結合非同步程式設計

工廠方法模式可以結合非同步程式設計來提高系統的可擴充套件性和可維護性。以下是結合非同步程式設計的例子:

import asyncio
from abc import ABC, abstractmethod

# Product
class Service(ABC):
    @abstractmethod
    async def perform_service(self):
        pass

# ConcreteProduct
class ConcreteService(Service):
    async def perform_service(self):
        print("Performing concrete service")

# Creator
class ServiceCreator(ABC):
    @abstractmethod
    async def factory_method(self) -> Service:
        pass

# ConcreteCreator
class ConcreteServiceCreator(ServiceCreator):
    async def factory_method(self) -> Service:
        return ConcreteService()

# 客戶端程式碼
async def main():
    creator = ConcreteServiceCreator()
    service = await creator.factory_method()
    await service.perform_service()

asyncio.run(main())

在這個例子中,ConcreteService類別定義了非同步的perform_service方法,ConcreteServiceCreator類別負責建立ConcreteService例項。客戶端程式碼使用ConcreteServiceCreator建立ConcreteService例項,並呼叫其perform_service方法。非同步程式設計被使用來演示工廠方法模式在非同步環境下的應用。

2.4 Abstract Factory Pattern: 產品家族的工廠模式

Abstract Factory Pattern 是一種設計模式,延伸了 Factory Method 模式的概念。這種模式將產品物件的建立封裝到一套工廠方法中,確保建立的物件是相容的,可以無縫地合作。

Abstract Factory Pattern 的核心思想

Abstract Factory Pattern 定義了一個抽象介面,宣告了一組用於建立不同產品的方法,這些產品屬於同一家族。抽象工廠的子類別提供了這些建立方法的實作,確保傳回的產品遵守某些設計約束或限制。這種模式促進了系統架構中的鬆散耦合和高內聚,並強制使用產品家族的一致性,從而減少了執行時不相容的風險,促進了設計的對稱性。

Python 中的 Abstract Factory Pattern 實作

下面是一個 Python 中的 Abstract Factory Pattern 實作範例,考慮一個系統必須支援兩個 UI 元件家族:按鈕和核取方塊。抽象產品介面定義如下:

from abc import ABC, abstractmethod

class Button(ABC):
    @abstractmethod
    def render(self):
        pass

class Checkbox(ABC):
    @abstractmethod
    def render(self):
        pass

接著,宣告一個抽象工廠,指定了建立每種型別產品的方法:

class UIFactory(ABC):
    @abstractmethod
    def create_button(self) -> Button:
        pass

    @abstractmethod
    def create_checkbox(self) -> Checkbox:
        pass

然後,實作具體的工廠類別和產品類別:

class WindowsUIFactory(UIFactory):
    def create_button(self) -> Button:
        return WindowsButton()

    def create_checkbox(self) -> Checkbox:
        return WindowsCheckbox()

class MacUIFactory(UIFactory):
    def create_button(self) -> Button:
        return MacButton()

    def create_checkbox(self) -> Checkbox:
        return MacCheckbox()

class WindowsButton(Button):
    def render(self):
        return "Windows Button"

class WindowsCheckbox(Checkbox):
    def render(self):
        return "Windows Checkbox"

class MacButton(Button):
    def render(self):
        return "Mac Button"

class MacCheckbox(Checkbox):
    def render(self):
        return "Mac Checkbox"

使用 Abstract Factory Pattern 的優點

Abstract Factory Pattern 提供了一種高效的方式來建立相容的產品家族,同時保持系統架構的鬆散耦合和高內聚。這種模式特別適合於需要支援多個產品變體或主題的系統,例如 GUI 工具包支援多個外觀標準、跨平臺應用程式或需要可交換服務提供者的系統。

抽象工廠模式的實作

抽象工廠模式是一種建立型設計模式,提供了一種方式來封裝一系列相關的產品家族,並且無需指定具體的類別。這種模式允許客戶端程式碼與抽象工廠介面合作,而不需要知道具體的產品類別。

產品介面

首先,我們需要定義產品介面。假設我們要建立一個使用者介面(UI),它包含按鈕和核取方塊兩種元件。因此,我們定義兩個介面:ButtonCheckbox

from abc import ABC, abstractmethod

class Button(ABC):
    @abstractmethod
    def render(self):
        pass

class Checkbox(ABC):
    @abstractmethod
    def render(self):
        pass

具體產品實作

接下來,我們需要為每個產品家族提供具體的實作。例如,要支援「Windows」和「Mac」兩種 UI 主題,我們可以定義如下類別:

class WindowsButton(Button):
    def render(self):
        return "渲染Windows風格按鈕"

class WindowsCheckbox(Checkbox):
    def render(self):
        return "渲染Windows風格核取方塊"

class MacButton(Button):
    def render(self):
        return "渲染Mac風格按鈕"

class MacCheckbox(Checkbox):
    def render(self):
        return "渲染Mac風格核取方塊"

抽象工廠介面

然後,我們需要定義抽象工廠介面。這個介面將提供方法來建立不同產品家族的例項。

class UIFactory(ABC):
    @abstractmethod
    def create_button(self) -> Button:
        pass

    @abstractmethod
    def create_checkbox(self) -> Checkbox:
        pass

具體工廠實作

現在,我們可以實作具體的工廠類別,這些類別將實作抽象工廠介面,並建立相應的產品例項。

class WindowsUIFactory(UIFactory):
    def create_button(self) -> Button:
        return WindowsButton()

    def create_checkbox(self) -> Checkbox:
        return WindowsCheckbox()

class MacUIFactory(UIFactory):
    def create_button(self) -> Button:
        return MacButton()

    def create_checkbox(self) -> Checkbox:
        return MacCheckbox()

客戶端程式碼

最後,在客戶端程式碼中,我們可以使用抽象工廠介面來建立不同產品家族的例項,而無需知道具體的類別。

def render_ui(factory: UIFactory):
    button = factory.create_button()
    checkbox = factory.create_checkbox()
    print(button.render())
    print(checkbox.render())

# 渲染Windows UI
windows_factory = WindowsUIFactory()
render_ui(windows_factory)

# 渲染Mac UI
mac_factory = MacUIFactory()
render_ui(mac_factory)

這樣,透過抽象工廠模式,我們可以輕鬆地切換不同的 UI 主題,而不需要修改客戶端程式碼。這提高了系統的靈活性和可擴充套件性。

綜觀軟體工程設計模式的演進,動態工廠與抽象工廠模式,乃至依賴注入的應用,都體現了系統設計追求彈性與可維護性的目標。深入剖析這些模式的核心架構,可以發現它們都圍繞著解耦物件建立與使用邏輯的核心理念。透過多維比較分析,動態工廠模式相較於傳統工廠模式,更能適應執行時的需求變化,提升了系統的擴充套件性;而抽象工廠模式則更進一步,將相關產品的建立封裝成家族,確保產品間的相容性。同時,依賴注入的應用則有效降低了物件間的耦合度,簡化了單元測試和程式碼維護的複雜性。然而,技術限制深析也顯示,過度使用這些模式可能導致程式碼結構變得繁瑣,增加理解成本。對於規模較小的專案,簡單的工廠模式或許已足夠。玄貓認為,技術團隊應權衡專案的實際需求和複雜度,選擇最合適的設計模式,並著重於程式碼的可讀性和可維護性,才能真正發揮設計模式的價值。未來,隨著程式語言和開發框架的演進,預見這些設計模式將與新的程式設計正規化(如非同步程式設計和函式式程式設計)更緊密地結合,衍生出更具彈性、更高效能的解決方案。密切關注這些新興的整合趨勢,將有助於開發者構建更具競爭力的軟體系統。