将算法封装到一个类中

时间:2020-03-06 14:56:03  来源:igfitidea点击:

我想知道将算法封装到一个类中的情况有多(不常见)?更具体地讲,与其具有多个在彼此之间转发通用参数的独立函数,不如:

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);
};

似乎非常实用,不必通过函数参数转发通用参数和中间结果。.但是我还没有看到这种"模式"被广泛使用。.可能的不利之处是什么?

解决方案

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

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

有一种解决该问题的设计模式。它称为"策略设计模式",我们可以在此处找到一些不错的信息。

"策略"的好处是,它使我们可以定义一系列算法,然后可以互换使用它们,而不必修改使用该算法的客户端。

我通常创建一个函子或者函数对象来封装我的算法。

我通常使用以下模板

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

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

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

这根本不是一个坏策略。实际上,如果我们有能力(使用C ++进行编程)定义某种类型的抽象超类,该抽象超类为基础功能定义了不透明的接口,则可以在运行时交换不同的算法(例如排序算法,例如)。如果我们选择的语言具有反射性,那么我们甚至可以拥有无​​限扩展的代码,从而允许加载和使用算法,而这些算法在编写所述算法的使用者时可能甚至不存在。这也使我们可以松散地耦合其他函数类和算法类,这有助于在大型项目上进行重构并保持完好无损。

当然,每当我们开始构建复杂的类结构时,都会有额外的体系结构,因此需要构建和维护代码。但是,我认为,从长远来看,带来的好处要大于这种不便之处。

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

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

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.
    }
}

问题能否更笼统地表达为:"当软件的主要思想只是运行算法时,我们如何使用面向对象的设计?"

在那种情况下,我认为像我们提供的设计是一个很好的第一步,但是这些事情通常取决于问题。

我认为良好的一般设计就像我们所拥有的一样。 。 。

class InputData {};
class OutputData {};

class TheAlgorithm 
{
private:
     //functions and common data

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

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