为什么 Execute Aroud 习语不被视为策略设计模式?

Why the Execute Aroud idiom is not considered a Strategy design pattern?

我越来越多地看到相同解决方案的新标签,但名称不同。在这种情况下,为什么我们不能简单地说 Execute Aroud 习语与 Strategy design pattern?

相同

当我读到 Jon Skeet’s answer 这个问题时:“什么是“执行周围”成语?”,他说:

it's the pattern where you write a method to do things which are always required, e.g. resource allocation and clean-up, and make the caller pass in "what we want to do with the resource".

在这种情况下,@jon-skeet 使用 executeWithFile(String filename, InputStreamAction action) 方法作为 执行始终需要的事情的方法示例 和接口 InputStreamAction 作为对我们想用资源做什么的抽象

  public interface InputStreamAction
  {
      void useStream(InputStream stream) throws IOException;
  }

将其与 Stratey design pattern 进行比较,为什么我们不能直接说接口 InputStreamAction 定义了一系列算法?并且,接口InputStreamAction的每个实现都对应一个具体的策略封装了一个算法。最后,这些算法是可以互换的,我们可以将 executeWithFile 与任何这些策略一起使用。

那么,为什么我不能将Jon Skeet’s answer解释为Stratey design pattern的应用示例呢?

顺便问一下,哪个成语先出现? Execute Around 还是 Strategy 设计模式?

虽然 Execute Around 习语通常与函数式编程有关,但我找到的唯一文档是在 Smalltalk Best Practice Patterns 1997 年的 Smalltalk 编程语言范围内的书中,它遵循 OO方法。

因为设计模式描述了经常性问题的一般解决方案,所以我们可以说执行周围和策略都是相同的解决方案解决不同的问题。所以,我问:我们真的需要一个不同的名称来标识相同的解决方案,当它应用于不同的问题时吗?

虽然我同意@iluwatar 的,这是交流不同想法的方式,但我仍然认为我可以传达 Execute Around 的想法说:"I used a Strategy to specify what I want to do with a resource, which is always setup and cleaned in the same manner."

所以 Execute Around 习语减少了歧义(这很好),但同时增加了设计模式的名称?而且,这是一个好习惯吗?

同时 Strategy and Execute Around are technically very similar they communicate different ideas. When we discuss interchangeable algorithms the term to use is Strategy。当我们围绕业务方法讨论分配和释放资源时,我们应该使用术语 Execute Around。

对我来说,策略模式是 "family of algorithms" 意味着有多种不同的方法可以实现特定目标。例如,有多个不同的 algorithms/strategies 可以实现对值列表进行排序的特定目标。但在给出的示例中——executeWithFile 处理文件的打开和关闭——我认为 InputStreamAction 系列没有任何特定目标。具体实现可能都有不同的目标。

在 Java 中,Execute Around 模式需要对象是接口的具体实现。我认为这就是它看起来与策略模式如此相似的原因。但在其他语言中,只需要一个普通的旧函数。以Ruby为例:

execute_with_file('whatever.txt') do |stream|
   stream.write('whatever')
end

没有InputStreamAction接口,也没有具体的WhateverWriterAction。只有一个函数将另一个函数作为参数。可以将普通的旧函数参数视为 "strategy" 吗?可能是,但我不会将其称为策略。当我使用或创建一个 Execute Around 实现时,我当然不会根据 Strategy 模式来考虑它。

总而言之,如果您想直白一点,您可以说 Execute Around 是一种特定类型的策略模式。然而,如果你考虑这两种模式背后的意图,它们是不同的想法:策略模式是实现特定目标的一系列算法,而执行周围是在块前后 运行 某些东西的通用方法任意代码。

在我看来,虽然两者可能是解决类似问题的方法,但它们是不同的成语,因此应该有不同的名称。

我称它们为成语,因为围绕它的执行只是一个 programming idiom,用于许多典型情况(类似于所介绍的情况)以及多种语言。而且,至少据我所知,Execute Around 从未正式成为一种软件设计模式,至少现在是这样。

它们为什么不同?这是我的观点:
Stategy 设计模式旨在(来自维基百科):

  • defines a family of algorithms,
  • encapsulates each algorithm, and
  • makes the algorithms interchangeable within that family.

通常 strategy 实例作为与上下文实例的长期关系,通常作为构造函数依赖项传递。即使上下文可能有策略的 setter,相同的 strategy 可以用于对上下文的多次调用,而调用者(客户端)甚至不知道调用者正在使用哪个特定上下文,此时调用已完成。此外,相同的策略实例可能会在其 public 接口的多个方法中被上下文使用,而调用者甚至不知道其用法。

另一方面,习语周围的执行适用于参数化算法,其中调用者(客户端)应始终在每次调用中传递算法参数化函数。因此,传递的 strategy 函数只会影响该特定调用的行为,不会影响其他调用。

尽管所呈现的差异可能在理论上和修辞上存在差异,但如果将上下文调用放在多线程场景中,我认为差异会更加明显和容易看到 "felt"。

如果没有大量的锁和同步,你不能在多线程场景中使用策略设计模式,至少在允许更改上下文策略的情况下。如果不这样做,您会看到上下文和策略之间的关系会持续更长时间,因为它们通常存在于同一时间。

execute around 成语如果实施得当,应该不会受到影响 "disease",至少如果传递的函数没有任何副作用的话。

总结一下,尽管 Strategy 设计模式和 execute around 习语可能有相似之处,可用于解决类似问题,并且可能seam 具有相似的静态结构,它们在本质上是不同的,前者更面向对象风格,后者更函数式风格,因此,应该有不同的名称!

我同意 Miguel Gamboa 的观点,意思相同的名称泛滥是不好的,应该避免。但是,至少在我看来,事实并非如此。

希望对您有所帮助!