【问题标题】:OOP C++: Which pattern: 2 classes with the partly same methodsOOP C++:哪种模式:2个类具有部分相同的方法
【发布时间】:2011-10-18 20:35:57
【问题描述】:

问题描述:

我需要实现 2 个类,如下所示:

class A1 {
 common_method1();
 common_method2();
 foo1();
};

class A2 {
 common_method1();
 common_method2();
 foo2();
};

foo1() 和 foo2() 有不同的逻辑。
foo1() 和 foo2() 可能有不同的参数和返回值。
常用方法相同或逻辑相似。

目标: 实现能够生成 A1 或 A2 对象的工厂。
调用 factory::create() 后,分别使用 foo1() 或 foo2() 方法来生成对象的类型。

问题 在 C++ C++/CLI 中如何更好地实现这样的逻辑?

谢谢!

【问题讨论】:

    标签: c++ oop inheritance design-patterns factory


    【解决方案1】:

    我认为这绝对是一种标准的继承模式。创建基类Parent,实现common_method1common_method2。创建继承自 Parent 的类 A1A2

    如果您需要在A1A2 中的common_method1common_method2 方法之一中进行一些特殊的大小写,请在Parent 中创建方法virtual

    分别在A1A2 中实现foo1foo2

    编辑:如果我理解正确,您想创建一个返回 Parent 类型引用(抽象类)的工厂。如果您想始终在A1 对象上使用foo1,在A2 对象上始终使用foo2,只需在Parent 接口中创建一个虚拟方法bar,在A1 中重写该方法将简单地调用foo1,并且,在 A2 中被覆盖,将简单地调用 foo2

    【讨论】:

    • Herb Sutter 和 Andrei Alexandrescu 足够称职吗?通过继承来重用基类的代码,你就错过了继承的意义。
    • Herb Sutter 和 Andrei Alexandrescu 是 C++ 老板。 :) n0rd,请提供解释。你的 POV 很有趣。
    • 在面向对象编程 (OOP) 中,继承是一种划分和重用代码的方法,方法是创建称为对象的属性和行为集合,这些属性和行为可以基于先前创建的对象。 en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)。我不认识 Herb 和 Andrei,但是,我确实认为实现重用是您应该使用继承的主要原因。如果不重用实现,还不如只使用接口来实现。
    • @DaddyM:很高兴你解决了你的问题。我们可以在其他地方进行“宗教”“继承并不意味着代码重用”的辩论...... ;)
    • 继承应该用来表达“是”关系。将其用于其他任何事情都是错误的。为了重用实现组合就足够了(但可能需要更多的输入)。阅读本书:gotw.ca/publications/c++cs.htm
    【解决方案2】:

    我将创建一个实现通用功能的基类。然后使用继承来创建最终类。

    您的工厂可以返回一个指向基类的指针,其中可能包含确定类型的方法。或者,如果需要,您可以键入 cast 它。

    【讨论】:

    • 如果类型不是 A2,dynamic_cast(base) 将为 NULL。这将是确定派生类型的最简单且不易出错的方法。
    • 如果您接下来要做的是确定对象的具体类并将基类指针转换为具体类指针,那么提取基类和创建工厂、返回指向该类对象的指针有什么意义?
    • 2 reece:dynamic_cast 的使用是糟糕设计的结果(Steven Dewhurst)。让我们考虑没有 dynamic_cast 的情况
    • 2 n0rd:我必须使用遗留代码。本案是我雇主意愿的结果。
    【解决方案3】:

    对您的示例了解不多,我认为您会想要创建一个包含常用方法的主类,然后将它们继承到几个基类。 然后您可以使用多态性来调用 foo1() 或 foo2()。 polymorphism 上的这个站点可能会对您有所帮助,因为它使用了经典的圆形/方形 draw() 示例。

    【讨论】:

      【解决方案4】:

      您可能希望有这样的层次结构:

      #include <iostream>
      
      struct A_Base {
          // You can put your other common method here
          virtual void common_method();
          virtual ~A_Base();
      }
      
      struct A1 : A_Base {
          void foo1();
      };
      
      struct A2 : A_Base {
          void foo2();
      };
      
      struct Factory {
          // I'm just using an int for the condition,
          // but you can use anything
          A_Base *CreateA(int i) {
              if( i == 1 ) return new A1;
              if( i == 2 ) return new A2;
          }
      };
      
      int main() 
      {
          Factory f;
      
          // Create an object
          A_Base *pb = f.CreateA(1);
      
          A1 *pa1;
          A2 *pa2;
      
          // Run a common method
          pb->common_method();
      
          // Check the runtime type
          // (not really necessary, but you might need it)
          if( pa1 = dynamic_cast<A1*>(pb) ) {
              pa1->foo1(); // Run the unique method
          } else if ( pa2 = dynamic_cast<A2*>(pb) ) {
              pa2->foo2(); // Or run the other unique method
          }
      
          // Delete the pointer
          delete pb;
          return 0;
      }
      

      是的,我在接近尾声时使用了 RTTI;不是很好的做法,但您可能需要知道如何进行基础->派生转换

      【讨论】:

        猜你喜欢
        • 2021-07-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-03
        • 2011-05-18
        • 2021-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多