将算法封装到类中

时间:2008-09-30 16:55:38

标签: design-patterns coding-style class-design

我想知道如何(一般)将算法封装到一个类中?更具体地说,不是使用许多单独的函数来转发彼此之间的公共参数:

void f(int common1, int param1, int *out1);
void g(int common1, int common2, int param1, int *out2)
{
  f(common1, param1, ..);
}

将公共参数封装到类中并完成构造函数中的所有工作:

struct Algo
{
  int common1;
  int common2;

  Algo(int common1, int common2, int param)
  { // do most of the work }

  void f(int param1, int *out1);
  void g(int param1, int *out2);
};

通过函数参数转发常见参数和中间结果似乎非常实用。但是我没有看到这种“模式”被广泛使用..有哪些可能的缺点?

6 个答案:

答案 0 :(得分:5)

有一种解决问题的设计模式;它被称为“战略设计模式” - 您可以在其上找到一些好的信息here

“策略”的好处在于,它允许您定义一系列算法,然后可以互换使用它们,而无需修改使用算法的客户端。

答案 1 :(得分:5)

这根本不是一个糟糕的策略。实际上,如果您具有使用您的语言(在C ++中执行)的能力来定义某种类型的抽象超类,它定义了底层功能的不透明接口,您可以在运行时交换不同的算法(想想排序算法,例如)。如果您选择的语言具有反射,您甚至可以拥有无​​限可扩展的代码,允许加载和使用算法,这些算法在编写所述算法的使用者时可能根本不存在。这也允许您松散地耦合您的其他功能类和算法类,这有助于重构并在处理大型项目时保持您的理智完整。

当然,无论何时开始构建复杂的类结构,都需要构建和维护额外的体系结构 - 因此需要代码。但是,在我看来,长远来看的好处超过了这个小小的不便。

最后一个建议:在构造函数中完成您的工作。构造函数应该仅用于将类内部结构初始化为合理的默认值。是的,这可能包括调用其他方法来完成初始化,但初始化是 not 操作。这两者应该是分开的,即使它需要在您的代码中再调用一次来运行您正在寻找的特定算法。

答案 2 :(得分:2)

你的问题可以更普遍地表达为“当软件的主要思想只运行算法时,我们如何使用面向对象的设计?”

在这种情况下,我认为像你这样的设计是一个很好的第一步,但这些东西通常都是依赖于问题的。

我认为一个好的通用设计就像你在那里一样。 。

class InputData {};
class OutputData {};

class TheAlgorithm 
{
private:
     //functions and common data

public:
   TheAlgorithm(InputData);      
   //other functions
   Run();
   ReturnOutputData();
};

然后,让它与您想要的main()或GUI进行交互。

答案 3 :(得分:1)

我通常会创建一个仿函数或Function Object来封装我的算法。

我通常使用以下模板

class MyFunctor {
    public:
       MyFunctor( /* List of Parameters */ );
       bool execute();
    private:
       /* Local storage for parameters and intermediary data structures */
}

然后我用这种方式使用了我的仿函数:

    bool success = MyFunctor( /*Parameter*/ ).execute();

答案 4 :(得分:1)

也许更好的方法(除非我遗漏了一些东西)是在类中使用ecapsualte算法并让它通过方法调用执行。您可以通过构造函数将所有参数传递给公共属性,也可以创建一个结构,该结构可以封装传递给包含算法的类的所有参数。但通常情况下,在构造函数中执行这样的事情并不是一个好主意。首先是因为它不直观。

public class MyFooConfigurator
{
   public MyFooConfigurator(string Param1, int, Param2) //Etc...
   {
      //Set all the internal properties here
      //Another option would also be to expose public properties that the user could
      //set from outside, or you could create a struct that ecapsulates all the
      //parameters.
      _Param1 = Param1; //etc...
    }

    Public ConfigureFoo()
    {
       If(!FooIsConfigured)
          return;
       Else
          //Process algorithm here.
    }
}

答案 5 :(得分:0)

如果您需要使用构造函数参数调用这两个方法,那么我会这样做。

如果您永远不需要使用相同的参数调用这两个方法,那么我就不会。