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 会更简单:
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)