Python中的工厂模式

cha*_*ver 22 python design-patterns factory factory-pattern

我目前正在用Python实现Factory设计模式,我有几个问题.

  1. 有没有办法阻止实际具体类的直接实例化?例如,如果我有一个生成Vehicle的VehicleFactory,我希望用户只使用该工厂,并防止任何人直接意外地实例化Car()或Truck().我可以在init()中抛出异常,但这也意味着工厂无法创建它的实例......

  2. 在我看来,工厂正在上瘾.似乎所有东西都应该成为工厂,这样当我改变内部实现时,客户端代码不会改变.我很想知道什么时候有实际需要使用工厂,什么时候不适合使用.例如,我可能有一个Window类,现在只有这种类型的一个(没有PlasticWindow,ReinforcedWindow或类似的东西).在这种情况下,我是否应该使用工厂为客户端生成Window,以防万一我以后可能会添加更多类型的Windows?

  3. 我只是想知道是否有通常的方式来调用工厂.例如,现在我将我的车辆工厂称为车辆,因此代码将类似于Vehicles.create(...).我看到很多教程就像VehicleFactory一样,但我发现它太长了,它也暴露了实现.

编辑:我所说的"暴露实施"是因为它让人们知道它是一个工厂.我觉得客户不需要知道它是一个工厂,而是作为一个可以为你返回对象的类(当然这是一个工厂,但也许没有必要明确告诉客户那个?).我知道这些代码很容易暴露,所以我并不是说"暴露源代码中实现功能的方式".

谢谢!

Hum*_*art 24

是Pythonic.不要使用"企业"语言(如Java)解决方案过度复杂化代码,这些解决方案会增加不必要的抽象级别.

您的代码应该简单直观.您不应该委托另一个类来实例化另一个类.

  • +1.模式通常(尽管不总是)是Java等语言的延续.在Python中使用它们之前,确保您绝对需要它们. (12认同)
  • @chaindriver:方式,方式太偏执了.他们可以阅读您的来源.您可以采取哪些可能的"预防措施"? (3认同)
  • @chaindriver:"但我无法重构类,因为客户端直接实例化了类".通常是假的.我想你可能会创造一种如此病态的局面,以至于无法前进.但这很难."他们的代码必须改变".嗯.你告诉他们?您提供向后兼容的替代方案?您分叉并提供支持的新版本和没有支持的旧版本?这些是简单的常见情况.看看Jinja这样的开源项目,他们转而使用Jinja2. (2认同)

Mat*_*ner 12

  1. 不要暴露类(例如,将其设为私有__MyClass,或明显不希望它直接使用_MyClass).这样它只能通过工厂函数实例化.
  2. 也许您应该检查关键字参数和继承的使用.听起来你可能会忽略这些,这通常会减少你对复杂工厂的依赖(说实话,我很少需要工厂).
  3. In Python you cannot easily protect against exposing implementation, it goes against the Zen of Python. (It's the same in any language, a determined individual can get what they want eventually). At most you should try to ensure that a user of your code does not accidentally do the wrong thing, but never presume to know what the end-user may decide to achieve with your code. Don't make it obfuscated and difficult to work with.

  • @chaindriver:可悲的是,第1点是这个答案中最不实用的部分. (4认同)
  • "程序员......可能会意外地使用错误的类".正确."预防"在这里没有多大帮助,是吗?他们阅读文档,他们没有遵循它们.他们的代码会崩溃.如果你写了很多聪明的"预防"代码,会有什么变化?它仍然在运行时**崩溃**.这是Python.所有崩溃都在运行时.要么是糟糕的编程(他们不遵守规则),要么是良好的编程(你确保它在运行时崩溃,因为它没有遵循规则.)预防没有进入它,是吗? (4认同)
  • 我认为第3点是最重要的.只需简单明了地做正确的事情,如果有人有特殊需求,你目前还没有预见到,那是可能的. (2认同)

S.L*_*ott 6

有没有办法阻止实际具体类的直接实例化?

为什么?您的程序员是否是拒绝遵守规则的邪恶反社会人士?如果你提供工厂 - 工厂做人们需要的 - 那么他们就会使用工厂.

你不能"防止"任何事情.记得.这是Python - 他们有源.

我应该使用工厂为客户端生成Window,以防万一我以后可能会添加更多类型的Windows吗?

咩.既不好也不坏.管理所有类层次结构和工厂细节可能会很麻烦.

添加工厂并不难.这是Python - 您始终拥有所有源代码 - 您可以使用它grep来查找类构造函数,并在需要时将其替换为工厂.

由于您可以grep用来查找和修复错误,因此您无需像在Java或C++中那样预先计划此类事情.

我看到很多教程就像VehicleFactory一样,但我发现它太长了,它也暴露了实现.

"太长"?它的使用很少,几乎不重要.使用长名称 - 它可以帮助其他人了解您正在做的事情.这不是代码高尔夫,其中击键次数最少.

"揭露实施"?首先,它没有任何暴露.其次,这是Python - 您始终拥有所有来源 - 一切都已暴露.

不要再考虑预防和隐私了.没用.

  • Re:"太长了":如果你发现自己经常输入长话,也许你需要一个支持自动完成的编辑器...... (2认同)
  • @BeauMartínez:"除非编译代码"?在.pyc文件中?拆卸它们是微不足道的.你在做什么? (2认同)
  • @ S.Lott:用户倾向于使用课程.假如我有一个API文档并且列出了Vehicle类.当用户看到它时,假设他们认为可以使用该类是合乎逻辑的.您所建议的类似于说任何部分代码都不应该进行错误检查,因为用户想知道如何正确使用所有类和方法.如果是这种情况,很难发现错误,因为我们没有排除某些不应该发生的情况.也许这就是Python的方式,我猜我还不习惯. (2认同)