这是一个常见的和/或命名的OOP模式吗?

时间:2016-10-11 09:51:00

标签: algorithm oop design-patterns

我想知道我经常使用的这种模式是否常见并且有一个名称:

  • 算法是一个类
  • 其参数通过类
  • 的构造函数传递
  • 调用无参数run方法会触发计算
  • 通过调用getter方法获取结果

一个例子(为简单起见,用Python表示):

class MyAlgorithm:

    def __init__(self, input, param1, param2):
        self.param1 = param1
        self.param2 = param2
        self.input = input

    def run(self):
        ...
        return self

    def getResultA(self):
        ...

    def getResultB(self):
        ...

作为第二个问题:这种模式的优点和缺点是什么?是否有充分的理由使用单独的run - 方法而不是让构造函数进行计算?

4 个答案:

答案 0 :(得分:3)

这是command pattern的变体。

关键是你可以将命令传递给其他代码执行,然后再读回结果,而执行代码不需要知道特定参数/返回操作类型。

对于进行计算的构造函数。构造函数不应该进行任何计算。周期。

答案 1 :(得分:1)

我怀疑这样的事情是相当普遍的。实际上,我在我的代码中使用过它。

主要用例是您拥有大量数据,并且您希望对其进行各种转换。例如,我可能有一个价格矩阵(开盘/高/低/收盘,实际上是4)和收益矩阵。

我想构建采用这些成分的输出并以各种方式混合它们。因此,例如,一个函数产生开盘价和收盘价之间的回报,另一个函数产生收益率与收盘价之比。你可以继续产生这些输出,有时你想要打开或关闭它们中的一些,所以有一种方法可以让它们分开。

所以你做了你所展示的。您在文件中有这些算法的列表,并将所有数据的所有引用传递给它们。然后循环遍历它们并点击“运行”,并查看输出。

优点:保持每个算法与其他算法分开,能够选择运行哪个算法。

缺点:需要将每个算法分成不同的单位,如果没有多个单位,则不值得。

为什么不在run方法中进行计算?它仍然可以运行,但通常我们希望将结构与计算分开。

听起来有点像https://en.wikipedia.org/wiki/Command_pattern。我正在寻找包含代表想法的东西。

答案 2 :(得分:1)

它是command模式,其意图是将某些类(具体的Command类)的主要操作的实现与其使用者(CommandHandler)分离。总之,执行someCommandObject.run();的客户端类没有任何方法参数,因此该具体类中的方法实现可以自由地实现特定于该特定类的任何所需操作。因此,客户端类可以自由地执行anyCommandObject.run();方法,因为它们的方法声明对于任何类型参数都不是严格的。

与Java Threads中的Thread.run();相同。

  

是否有充分的理由选择单独的run-method而不是   让构造函数进行计算?

是。构造函数应该从不进行显式计算。构造函数的目的只是构造对象,而不是发现任何行为。如果你想公开它们,那就是方法的原因。

答案 3 :(得分:0)

第一个回答:

  

我想知道我经常使用的这种模式是否常见[...]

我在几个API中广泛地遇到过它。我不介意在记录时使用(在run()结果之前需要get()等),尽管有时输入对象很多,但很难设置正确。然而,很少有文件完整,如果它们完全是必要的,那么它可以做得更好。

然而,当我不得不扩展它时,事实证明非常麻烦(要求Ctor很乱,结果有时难以扩展,状态未知(还有run()吗?),某些结果对象可能是不可用的(好的)原因)...

第二个答案:

  

我想知道我经常使用的这种模式是否有一个名字:

正如其他人所说,看起来像Command Pattern。

现在就可扩展性发表一些意见:

(带上一粒盐,可能不适用于您的申请。)

  
      
  • 算法是一个类
  •   

这很好。 (对实体的算法包含) 但这不是非常可扩展的 - 只能通过继承来限制。太多的API强制继承,因为他们认为它们是应用程序的核心。如果我想扩展其他工作来完成这项工作,例如Map怎么办? 更好的是:

  • 可以通过界面
  • solver班级进行互动
  • 一个或多个具体类提供algorithm
  • 的可交换solver实现

当我想要一个求解器实例时,我可以通过完全自由地扩展接口来创建一个,或者通过(多个)继承重用一些已知的实现。

  
      
  • 其参数通过类
  • 的构造函数传递   

这是一个实现细节。为什么强迫某人处理他们可能不关心的物体?您如何甚至强制构造函数具有特定参数?如果初始状态是复杂且多方面的,并且需要Builder

,该怎么办?

没有模式应该要求一个特定的构造函数(除了空的一个?)。另外,请注意constructors shouldn't do too much computation

  
      
  • 调用无参数运行方法会触发计算
  •   
  • 你如何确保多次不被调用?
  • 或者它甚至在 getResult()方法之前被称为
  • 如果我再次运行(),我会得到相同的结果吗?
  • 或计算再次发生?
  
      
  • 通过调用getter方法获取结果
  •   
  • 但他们什么时候准备好了?结果对象需要null - 能够( ugh ),OptionalResult,或者有isAvailable()方法。
  • 结果会变得陈旧()吗?
  • 如何在不共享整个算法的情况下共享这些结果?
  • 之后如何处理Algorithm实例?它可以重复使用吗?我可以reset()吗?我的设置成本可能很高。

我发现它在我找到它的地方更清楚了(JAVA在这里):

 public interface Solver {
     <? extends SolverResult> run(SolverInput input);
 }

在这里,实现可以变化,解算器的每个实例都有一个完全内部状态,可以加速它(如缓存)供以后使用,但不同于SovlerResult对象,这是我想要的。可以根据需要创建SolverInput,SolverResult可以是求解器实例的专用结果类,能够提供更好的洞察力(使用额外的getComputationQuality()getConvergenceRate()等。)

我认为separating输入,求解器和输出更加灵活。设计模式不应该是强制执行工具,而应该是协调器工具。它甚至可以通过一次实现所有三个接口来实现您的设计模式(不是我推荐的)。