【问题标题】:Encapsulating an algorithm into a class将算法封装到一个类中
【发布时间】:2008-09-30 16:55:38
【问题描述】:

我想知道将算法封装到一个类中有多常见?更具体地说,不是有许多单独的函数在彼此之间转发公共参数:

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

不必通过函数参数转发公共参数和中间结果似乎很实用..但我还没有看到这种“模式”被广泛使用..可能的缺点是什么?

【问题讨论】:

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


    【解决方案1】:

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

    当然,无论何时开始构建复杂的类结构,都会有额外的架构——因此也就是代码——需要构建和维护。但是,在我看来,从长远来看,好处大于这种轻微的不便。

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

    【讨论】:

      【解决方案2】:

      有一种设计模式可以解决这个问题;它被称为“策略设计模式”——你可以找到一些关于它的好信息here

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

      【讨论】:

        【解决方案3】:

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

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

        我认为一个好的总体设计就像你所拥有的那样。 . .

        class InputData {};
        class OutputData {};
        
        class TheAlgorithm 
        {
        private:
             //functions and common data
        
        public:
           TheAlgorithm(InputData);      
           //other functions
           Run();
           ReturnOutputData();
        };
        

        然后,让它与 main() 或你的 GUI 交互,但你想要。

        【讨论】:

          【解决方案4】:

          我通常创建一个仿函数或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();
          

          【讨论】:

          • 我希望函数对象使用 operator() 来执行
          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

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

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

            【讨论】:

              猜你喜欢
              • 2013-04-15
              • 2015-04-15
              • 2019-05-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-02-11
              相关资源
              最近更新 更多