(使用Python 3.2,但我怀疑它很重要。)
我有class Data
,class Rules
和班级Result
。我使用小写来表示类的实例。
rules
对象包含的规则,如果应用于data
对象,则可以创建result
对象。
我决定将实际应用规则的(相当复杂和不断发展的)代码放到数据的哪个位置。我可以看到两个选择:
将该代码放入类Result
方法中,例如parse_rules
。 Result
构造函数将rules
对象作为参数,并将其传递给self.parse_rules
。
将该代码放入新类ResultFactory
中。 ResultFactory
将是一个单例类,它有一个方法,比如build_result
,它将rules
作为参数并返回一个新构建的result
对象。
这两种方法的优点和缺点是什么?
答案 0 :(得分:3)
GRASP design principles提供了在面向对象设计中为类和对象分配责任的指南。例如, Creator 模式表明:通常,如果以下一个或更好的更多,B类应负责创建A类实例:
在您的示例中,您将复杂且不断发展的代码应用于数据规则。这表明使用了Factory Pattern。
将代码置于结果中是禁忌的,因为1)结果不会创建结果,2)结果不是信息专家(即他们没有大部分所需的知识)。
简而言之, ResultFactory 似乎是一个合理的地方,可以集中了解如何将规则应用于数据来生成结果。如果你试图将所有这些逻辑推入结果或规则的类构造函数中,那么就会导致紧密耦合和内聚力的丧失。
答案 1 :(得分:2)
您可能需要考虑第三种情况:
Rules.__call__
中
实例化Result
,例如:result = rules(data)
<强>优点:强>
Result
可能完全不知道生成它们的Rules
(甚至可能是原始的Data
)。Rules
子类都可以自定义其Result
创建。Rules
适用于Data
收益Result
。Rules
的实例具有Result
实例的初始化信息,并在创建时传递。副作用:
Rules
和Data
之间的耦合:
Rules
Rules
应该能够决定应用哪些数据。答案 2 :(得分:1)
为什么不将规则放在自己的课程中?如果您创建RuleBase类,则每个规则都可以从中派生。这样,当应用数据需要规则时,可以使用多态。数据不需要知道或关心应用了哪些规则实例(除非数据本身是知道应该应用哪些规则的人。)
当需要调用规则时,数据实例可以是所有RuleBase.ExecuteRules()并将其自身作为参数传递。如果Data知道哪个规则是必要的,则可以直接从Data中选择Rule的正确子类。或者可以使用其他一些设计模式,例如Chain of Responsibility,其中Data调用模式并让Result返回。
这将是一次很棒的白板讨论。
答案 3 :(得分:1)
你能使ResultFactory成为一个纯函数吗?如果你需要的只是一个函数,那么创建一个单例对象是没用的。
答案 4 :(得分:0)
Result
需要Rules
来创建一个实例,并且您不能创建一个实例,那么它应该将其作为__init__
的参数。没有必要的购物模式。