战略模式应该是无国籍的吗?

时间:2011-05-30 13:23:37

标签: design-patterns strategy-pattern stateless

一个“四人帮”策略的类必须是完全无状态的(即没有字段),还是可以包含不可变状态(即最终字段)?

5 个答案:

答案 0 :(得分:17)

策略类封装了一个动作,而不是一个东西。因此,尽管如果你真的不得不这样做,但保持状态并不是很有意义。把它想象成动词,而不是名词。或者至少作为描述动作的名词。另一方面,您可以始终参数化策略,并通过方法调用或类似方法将客户端对象的状态传递给它。

此外,类是无状态还是有状态并不真正依赖于其字段上的final关键字。例子:

  • 在对象final上使用时,仅表示不能更改对对象的引用。您仍然可以更改该对象的内容,例如其字段。在这种情况下,你的班级是有状态的,尽管它的领域是最终的。
  • 如果该字段确实是一个常数,那么对于大多数意图和目的,您可以认为它是无状态的。例如,您可以声明一个字段private static final,然后确保您永远不会做任何事情来更改引用对象的状态。

编辑:让我们尝试区分策略本身的参数和该策略的一个特定执行的参数。如果策略类是无状态的,那么拥有该类的多个实例是没有意义的,这使得对象(而不是类)表示操作本身,而方法执行表示该策略的一个特定执行。

现在,如果我们有一个策略本身的参数,那么只有该参数对该策略的所有执行具有相同的值才有意义。因此,它可以放在一个常量的方法调用中,该方法调用返回一个常量(如果我们不是静态的东西),甚至是硬编码的。如上所述,这可以以无状态的方式实现。

另一方面,如果参数描述了策略的一个特定执行,那么只需将其作为参数传递给方法。它会。

附加说明:如果我们想要使用某种具有延迟,调度的执行行动队列,则有充分的理由使用在其状态中打包的“副词”的操作对象...有一种模式太 - 命令。

答案 1 :(得分:4)

不,为什么它应该是无国籍的?策略可以是任何东西,它只是代表一些运行时可插入的功能单元,允许您扩展修改消耗类的行为。据我所知,没有任何内容表明无国籍的要求,也没有不可变性。

答案 2 :(得分:3)

策略模式的目的是直接在方法局部范围内处理策略方法参数。策略类本身当然可以在需要时保存一些字段,但是方法参数不应该分配给那些字段,因为如果策略对象被多次使用,它可能会引入线程安全问题。

答案 3 :(得分:3)

无国籍状态是指在策略运行之间不保留任何数据;也就是说,如果你执行两次相同的策略,那么之前的策略运行都不会延续。这是有益的,因为它可以节省您在需要时“重置”策略实施的麻烦。

请注意,在策略模式实现的描述中,他们引用了一个上下文(我的书中的@ 317页),其中包含策略需要执行的数据。实现所需的所有“状态”应该可以放在这些上下文对象中。

这意味着策略实现本身是无状态的,但整个模式具有状态,因为所需数据在上下文中传递。

例如,如果您有数学运算的策略实现,那么至少有两种方法可以实现。第一种是在构造策略实现时在策略实现上设置arg1和arg2(以及3和4 ...)。然后,当您执行实现时,将获取其字段并执行操作。问题是,如果再次运行相同的实现,则必须重置其所有字段(或创建新实现)。

第二种方法是创建一个包含所有参数的上下文。 stategy实现将从上下文中获取所需的值。然后,您可以重用策略实现的每个实例,每次只传递一个新的上下文。无需担心重新创建实现的新实例,或忘记重置实现实例。当然,您仍然需要正确管理上下文。

答案 4 :(得分:1)

是的,因为这主要是算法选择器。具体算法可以有状态,但不是选择器。

顺便说一句,在这个策略中,我们没有一个班级。你的意思是哪个具体课程?在什么角色?