使用工厂与常规构造函数的利弊

时间:2012-01-16 01:52:30

标签: python oop design-patterns architecture class-factory

(使用Python 3.2,但我怀疑它很重要。)

我有class Dataclass Rules和班级Result。我使用小写来表示类的实例。

rules对象包含的规则,如果应用于data对象,则可以创建result对象。

我决定将实际应用规则的(相当复杂和不断发展的)代码放到数据的哪个位置。我可以看到两个选择:

  1. 将该代码放入类Result方法中,例如parse_rulesResult构造函数将rules对象作为参数,并将其传递给self.parse_rules

  2. 将该代码放入新类ResultFactory中。 ResultFactory将是一个单例类,它有一个方法,比如build_result,它将rules作为参数并返回一个新构建的result对象。

    < / LI>

    这两种方法的优点和缺点是什么?

5 个答案:

答案 0 :(得分:3)

GRASP design principles提供了在面向对象设计中为类和对象分配责任的指南。例如, Creator 模式表明:通常,如果以下一个或更好的更多,B类应负责创建A类实例:

  • B的实例包含或复合聚合A
  • 的实例
  • A
  • 的B记录实例的实例
  • B的实例密切使用A
  • 的实例
  • B的实例具有A实例的初始化信息,并在创建时传递。

在您的示例中,您将复杂且不断发展的代码应用于数据规则。这表明使用了Factory Pattern

将代码置于结果中是禁忌的,因为1)结果不会创建结果,2)结果不是信息专家(即他们没有大部分所需的知识)。

简而言之, ResultFactory 似乎是一个合理的地方,可以集中了解如何将规则应用于数据来生成结果。如果你试图将所有这些逻辑推入结果或规则的类构造函数中,那么就会导致紧密耦合和内聚力的丧失。

答案 1 :(得分:2)

第三种情况:

您可能需要考虑第三种情况:

  • 将代码放在方法Rules.__call__中 实例化Result,例如:result = rules(data)

<强>优点:

  • Result可能完全不知道生成它们的Rules(甚至可能是原始的Data)。
  • 每个Rules子类都可以自定义其Result创建。
  • 感觉自然(对我而言):Rules适用于Data收益Result
  • 您将拥有一些GRASP原则:
    • 创建者Rules的实例具有Result实例的初始化信息,并在创建时传递。
    • 信息专家:信息专家将负责在课程中负责实现该课程所需的最多信息。

副作用:

  • 耦合:您将提升RulesData之间的耦合:
    • 您需要将整个数据集传递给每个Rules
    • 这意味着每个Rules应该能够决定应用哪些数据。

答案 2 :(得分:1)

为什么不将规则放在自己的课程中?如果您创建RuleBase类,则每个规则都可以从中派生。这样,当应用数据需要规则时,可以使用多态。数据不需要知道或关心应用了哪些规则实例(除非数据本身是知道应该应用哪些规则的人。)

当需要调用规则时,数据实例可以是所有RuleBase.ExecuteRules()并将其自身作为参数传递。如果Data知道哪个规则是必要的,则可以直接从Data中选择Rule的正确子类。或者可以使用其他一些设计模式,例如Chain of Responsibility,其中Data调用模式并让Result返回。

这将是一次很棒的白板讨论。

答案 3 :(得分:1)

你能使ResultFactory成为一个纯函数吗?如果你需要的只是一个函数,那么创建一个单例对象是没用的。

答案 4 :(得分:0)

嗯,第二个是彻头彻尾的愚蠢,尤其是所有的单身。如果Result需要Rules来创建一个实例,并且您不能创建一个实例,那么它应该将其作为__init__的参数。没有必要的购物模式。