Python中的工厂模式

23 投票
3 回答
17484 浏览
提问于 2025-04-16 02:57

我现在正在用Python实现工厂设计模式,有几个问题想请教。

  1. 有没有办法防止直接创建具体的类?比如说,我有一个叫VehicleFactory的工厂,它负责生成车辆。我希望用户只使用这个工厂,而不是让他们不小心直接创建Car()或Truck()。我可以在init()里抛出一个异常,但这样的话工厂自己也无法创建这些实例了……

  2. 现在我觉得工厂模式有点上瘾。感觉好像所有东西都应该变成工厂,这样当我改变内部实现时,客户端的代码就不需要改动。我想知道什么时候真的需要使用工厂,什么时候又不适合使用。比如,我可能有一个Window类,现在只有这一种类型(没有PlasticWindow、ReinforcedWindow之类的)。在这种情况下,我应该使用工厂来让客户端生成Window吗?以防将来我可能会添加更多类型的Window?

  3. 我在想有没有一种常见的方式来调用工厂。比如,现在我把我的车辆工厂叫做Vehicles,所以代码会像这样:Vehicles.create(...)。我看到很多教程用VehicleFactory这个名字,但我觉得太长了,而且有点暴露实现细节。

补充说明:我所说的“暴露实现”是指让人们知道这是一个工厂。我觉得客户端不需要知道这是一个工厂,而是应该把它看作一个可以为你返回对象的类(当然它是工厂,但也许没必要明确告诉客户端这一点?)。我知道源代码很容易被查看,所以我并不是说“暴露源代码中功能的实现方式”。

谢谢!

3 个回答

6

有没有办法防止直接创建具体的类实例?

为什么?难道你的程序员都是不守规矩的坏人吗?如果你提供一个工厂(就是一个专门用来创建对象的地方)——而且这个工厂能满足大家的需求——那么他们就会使用这个工厂。

你不能“防止”任何事情。记住,这里是Python——他们可以看到源代码。

我应该为客户端使用一个工厂来生成窗口吗?以防将来我可能会添加更多类型的窗口?

嗯,这个问题没什么好坏之分。管理所有的类层次结构和工厂细节可能会变得麻烦。

添加一个工厂并不难。这是Python——你随时都能看到源代码——你可以用grep来查找类的构造函数,并在需要的时候用工厂替换它。

因为你可以用grep来找到并修正错误,所以你不需要像在Java或C++中那样提前计划这些事情。

我看到很多教程都是用VehicleFactory这样的名字,但我觉得太长了,而且有点暴露实现细节。

“太长了”?这个名字用得很少,所以其实没什么大不了的。用长一点的名字——这能帮助别人理解你在做什么。这不是一个拼写比赛,谁打字少谁就赢。

“暴露实现细节”?首先,它根本没有暴露什么。其次,这里是Python——你随时都能看到源代码——一切都已经暴露了。

别再过于担心防止和隐私的问题了。这并没有什么帮助。

23

要做到“Pythonic”,也就是要用Python的风格来写代码。不要把代码搞得太复杂,像一些“大企业”用的语言(比如Java)那样,增加不必要的复杂层次。

你的代码应该简单明了,容易理解。你不需要通过另一个类来创建新的对象,这样会让事情变得麻烦。

12
  1. 不要让这个类暴露出来,比如可以把它设为私有的 __MyClass,或者让它看起来不想被直接使用 _MyClass。这样的话,用户只能通过工厂函数来创建这个类的实例。
  2. 你可能需要看看关键字参数和继承的用法。听起来你可能忽略了这些,它们通常能减少你对复杂工厂的依赖(说实话,我很少需要用到工厂)。
  3. 在Python中,你不能轻易防止别人看到你的实现,这和Python的哲学是相悖的。(在任何语言中都是这样,想要搞明白的人最终都能找到办法)。你最多只能确保使用你代码的人不会不小心做错事,但永远不要假设最终用户会用你的代码去实现什么。不要让代码变得晦涩难懂,难以使用。

撰写回答