理解Python中的工厂设计模式

问题描述 投票:0回答:1

Refactoring Guru中工厂模式的Python版本是:

from __future__ import annotations
from abc import ABC, abstractmethod


class Creator(ABC):
    @abstractmethod
    def factory_method(self) -> Product:
        pass

    def some_operation(self) -> str:
        product = self.factory_method()
        result = f"Creator: The same creator's code has just worked with {product.operation()}"
        return result

class ConcreteCreator1(Creator):
    def factory_method(self) -> Product:
        return ConcreteProduct1()


class ConcreteCreator2(Creator):
    def factory_method(self) -> Product:
        return ConcreteProduct2()


class Product(ABC):

    @abstractmethod
    def operation(self) -> str:
        pass

class ConcreteProduct1(Product):
    def operation(self) -> str:
        return "{Result of the ConcreteProduct1}"


class ConcreteProduct2(Product):
    def operation(self) -> str:
        return "{Result of the ConcreteProduct2}"


def client_code(creator: Creator) -> None:
    print(f"Client: I'm not aware of the creator's class, but it still works.\n"
          f"{creator.some_operation()}", end="")


if __name__ == "__main__":
    client_code(ConcreteCreator1())
    client_code(ConcreteCreator2())

老实说,我有点犹豫在这里问这个问题,因为这看起来是一个非常简单的问题,但我在这里:

  • 引入
    ConcreteCreatorX
    类与像下面这样直接传递
    Product
    类型相比有什么好处?
from abc import ABC, abstractmethod
from typing import Any

class Product(ABC):
    @abstractmethod
    def operation(self) -> Any:
        pass

class ConcreteProduct1(Product):
    def operation(self) -> str:
        return "{Result of the ConcreteProduct1}"


class ConcreteProduct2(Product):
    def operation(self) -> str:
        return "{Result of the ConcreteProduct2}"
    
def client_code(product: Product) -> None:
    print(f"Client: I'm not aware of the creator's class, but it still works.\n"
          f"{product.operation()}")

if __name__ == "__main__":
    client_code(ConcreteProduct1())
    client_code(ConcreteProduct2())

在这两种情况下,

client_code
都需要某种实现
operation
方法的类型。
Product
类型已经以抽象的方式提供了这样的方法,以便每个
Product
都可以实现自己的方法变体。因此,从
client_code
的角度来看,我认为使用其中之一没有什么区别。

现在,两个代码之间存在差异:第一个示例(实际的工厂模式示例)是将每个

ConcreteProductX
类的实例化委托给
ConcreteCreatorX
类(我理解这是该模式的全部要点)。

我们是分离关注点,这样,当然,如果我们想修改工厂方法,我们不需要直接修改

Product
类。我可以看到,如果我们想要修改
factory_method
来执行除了实例化
ConcreteProductX
类之外的其他操作,例如在某处通知某项内容、跟踪创建了多少产品等,那么我们不会这样做吗?打破单一责任原则?因为现在
Creator
不仅仅负责创造产品。或者说,是否有资格被称为
Creator

所以我想我的问题可以用更精确的方式重新表述:

  • 在不违反单一职责原则的情况下,使用
    Creator
    ConcreteCreatorX
    类有什么好处吗?
python design-patterns factory-pattern
1个回答
0
投票

当你不能传递函数本身作为参数,只能传递一个提供你想要调用的方法的对象时,就需要这种设计。

惯用的 Python 会更简单:

type Creator = Callable[[], str]

def client_code(creator: Creator) -> None:
    print(f"Client: I'm not aware of the creator's class, but it still works.\n"
          f"{creator()}", end="")


def factory1() -> str:
    ...

def factory2() -> str:
    ...

client_code(factory1)
client_code(factory2)
© www.soinside.com 2019 - 2024. All rights reserved.