6

我与某人就战略模式的真正含义发生了一场极客之争,我需要一位专家来解决这个问题。

我们都同意策略模式允许在运行时交换类的内容(例如行为),同时保持相同的接口。然而,她的论点是“为了使 [算法] 成为一种策略,你必须得到相同的结果”。我的论点是,交换“算法”或类的逻辑可能意味着覆盖操作的结果不同,但它仍然符合策略模式的目的、意图(和分类)。

她带有注释的代码示例:


根据您的定义,一个类的任何子类都是一种策略。它们具有相同的方法定义(签名),因此可以互换。

Interface Strategy
{
    DoArithmatic(int[] a)
}

Class A : Strategy
public int DoArithmatic(int[]a)
{
     int temp = 0;
     for(int i =0; i< a.length; i++)
          temp += a[i]
}

Class B : Strategy
public int DoArithmaticB(int[]a)
{
     int temp = 0;
     for(int i =a.length -1; i>-1; i--)
          temp += a[i]
}

Class C : Strategy
public int DoArithmatic(int[]a)
{
     int temp = 0;
     for(int i =0; i< a.length; i++)
          temp -= a;
}

int[] a = { 1,2,3 }
ClassA.DoArithmatic(a) = 6
ClassB.DoArithmatic(a) = 6
ClassC.DoArithmatic(a) = -6//This one is not interchangeable

前两个是策略。因为对于任何输入,他们都会给你完全相同的答案。最后一个不是。仅仅因为它给你一个 int 并不能使它成为一种策略。他们必须“做”同样的事情。

您不能仅仅为了使它们成为一种策略而使用“更高”的抽象术语。

这些都做“数学”,但他们并不是都以不同的方式做“相同”的事情。这就是战略的本质。

那么,谁是对的?

4

9 回答 9

11

您先生是正确的,您的同事需要阅读 GoF。

“策略模式让算法独立于使用它们的客户而变化。”

看:

http://www.dofactory.com/Patterns/PatternStrategy.aspx

于 2009-03-26T13:42:38.640 回答
6

从技术上讲,策略可以为所欲为。

只有当“外部环境”规定了一些无法在编程界面中捕获的固定且可重复的行为(称它们为“理想的属性”)时,您才需要注意您的策略是真正可替代的 à la Liskov这些理想的属性。

于 2009-03-26T13:54:15.087 回答
4

我支持你的意见。只要可以在相同的上下文中使用不同的策略,它们就可以做非常不同的事情。

例如,如果您想访问树中的每个节点,有效的策略可能是:

  • 深度优先搜索预订
  • DFS 后订单
  • BFS
  • 随机的
  • ...

所有策略都会以不同的顺序访问节点,但目标(访问每个节点)是相同的。因此,如果顺序无关紧要,任何一种策略都适合您的需求。

于 2009-03-26T13:45:07.340 回答
3

FWIW,维基百科的文章同意你的观点,从未听说过她的立场。

于 2009-03-26T13:54:09.283 回答
3

前两个是策略。因为对于任何输入,他们都会给你完全相同的答案。最后一个不是。只是因为它给了你一个 int 并不能使它成为一种策略。他们必须“做”同样的事情。

他们必须做同样的事情,但这并不意味着他们给出完全相同的结果。来自 GoF 的激励示例是不同的布局算法或不同的寄存器分配算法之一。这些策略具有相同的目标——在页面上布局文本和图像块,或将虚拟寄存器分配给硬件寄存器——但它们不必创建完全相同的结果。

因此,如果Strategy您示例中的目标是对输入进行任何算术运算,那么每个示例都是该目标的策略。如果目标是对传递的数组求和,DoArithmatic则会被调用CalculateSum,最后一个示例将不符合策略约定,因此违反LSP

于 2009-03-26T14:01:34.320 回答
2

根据“Head first Design Patterns”(参见此处)第 24 页

“策略模式定义了一系列算法,
封装了每个算法,并使它们可以互换。
策略让算法独立于
使用它的客户而变化。”

所以先生,您是正确的,至少根据定义模式的人来说,但他们知道什么。

于 2009-03-26T13:53:38.770 回答
2

你是。该策略的重点是替换算法。它们是否提供相同的结果是所需行为的副产品。

于 2009-03-26T13:55:06.223 回答
2

我认为更正确的说法是策略是否必须在确定性上相同的问题超出了策略模式定义的范围。

如果一个函数对于给定的输入总是返回相同的结果,那么它是确定性的。如果两个函数是确定性的,并且它们总是为相同的输入返回相同的值,那么它们在确定性上是等价的。它们可能有也可能没有相同的副作用;如果他们这样做了,那么他们就是完全等价的。

通常情况并非如此。让我们考虑一个似乎需要确定性等价的例子:排序。您可能会认为,如果两个比较器实现无法为相同的输入返回相同的结果,那么其中至少一个肯定是有问题的,但情况不一定如此。

排序顺序因国家/地区而异。有些地方对重音不敏感。有些人把 McDuck 和 MacDuck 放在一起,等等。这些是策略,这是策略模式的完美应用,而且这些策略肯定不是确定性等价的。

你赢了。

于 2009-03-26T14:29:07.403 回答
0

我也不得不同意。一个很好的例子是定价计算器策略。您可以有不同的策略来计算发票的最终金额,具体取决于项目数量、客户类型、运输目的地等几个变量。这些策略中的每一个肯定会返回不同的结果,并且仍然会被考虑策略模式。

于 2009-03-26T13:46:05.183 回答