10

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

4

5 回答 5

18

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

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

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

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

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

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

附加说明:有一个很好的理由使用带有“副词”的动作对象,如果我们想要,比如说,有某种延迟执行的动作队列,调度......这也有一个模式 - 命令.

于 2011-05-30T13:35:01.090 回答
6

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

于 2011-05-30T13:27:56.973 回答
5

无状态是指在策略运行之间不保留任何数据的事实;即,如果您两次执行相同的策略,则上一次策略运行的任何内容都不会延续。这是有益的,因为它为您省去了在需要时必须“重置”您的策略实现的麻烦。

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

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

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

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

于 2011-05-30T13:32:53.913 回答
3

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

于 2011-05-30T13:31:20.687 回答
0

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

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

于 2011-05-30T13:31:38.597 回答