【问题标题】:Avoiding duplication of code in common classes避免公共类中的代码重复
【发布时间】:2012-03-13 18:44:44
【问题描述】:

我有一个回调函数,叫做

MyCallBack(int type)

我有 3 个类 B、C 和 D 从 A 派生,具有通用方法名称 目前我的代码是这样的

MyCallBack(int type){
if(type == 1 ){
B b;
b.perform();
}else if(type==2) {
C c;
c.perform();
}else if(type ==3){
D d; 
d.perform();
}

有没有办法可以减少这段代码,比如

MyCallBack(int type){
Common object(type);
object.perform();
}

【问题讨论】:

    标签: c++ design-patterns inheritance


    【解决方案1】:

    基本上,您需要的是多态性。

    你所有的类B,C,D都应该派生自一个抽象类说SuperBase和一个纯虚方法perform()
    您的代码应仅使用指向 SuperBase 的指针,其中包含实际具体类对象的地址。
    一旦你有了这个,根据被指向对象的实际类型,来自适当类的方法将被调用。

    这种方法的优点是没有硬编码类型检查以及使用Open Closed principle 的松散耦合设计的灵活性。

    【讨论】:

      【解决方案2】:

      @Als 使用多态的想法是一个很好的想法 (IMO),但它只有在您将输入整数转换为实际类型之后 才真正起作用。一种方法是索引一个指向对象的指针数组:

      MyCallback(int type) { 
          static A *ptrs[] = { new B, new C, new D};
      
          ptrs[type-1]->perform();
      }
      

      编辑:以防万一您不知道,为了使其正常工作,perform 需要是在A 中声明的(可能是纯的)虚函数,并在每个B 中定义, CD。您需要确保函数的整个签名,而不仅仅是名称,在类之间是相同的。

      【讨论】:

        【解决方案3】:

        interface 怎么样?

        class A
        {
            public:
        
                virtual void perform() = 0;
        };
        
        class B : public A
        {
            public:
        
                void perform() { ... }
        };
        
        // Same for C, and D
        

        所以你的回调看起来像:

        MyCallBack(A& performer)
        {
            performer.perform();
        }
        

        如果不能更改回调的签名,那abstract factory pattern

        function A* AFactory(int type)
        {
            switch(type)
            {
                case 1: return new B();    // Assuming B, C, D all derive from A
                case 2: return new C();
                case 3: return new D();
                default: return nullptr;  // nullptr is a c++11 thing.  Use NULL, if you're still on C++03
            }
        }
        

        然后是回调...

        MyCallBack(int type)
        {
            std::unique_ptr<A> obj(AFactory(type));  // this will automatically release the memory once it falls out of scope
            obj->perform();
        }
        

        【讨论】:

        • 不应该是MyCallBack(A&amp; performer)通过一个指针(即MyCallBack(A* performer))然后用performer-&gt;perform()调用它吗?
        • 通过引用基类来引用派生类是合法的。当然,如果传入的是 A*,那么他必须使用 A*。在可能的情况下,人们应该更喜欢对指针的引用。
        【解决方案4】:

        您应该创建对象工厂或只是静态(全局)方法返回指向基类型的指针(或引用,可能),但包含派生类型的对象。

        CBase* CreateObjectBasedOnType(int type)
        {
            // check for type and return appriopriate derived object
        }
        
        MyCallBack(int type)
        {
            CreateObjectBasedOnType(type)->perform();
        }
        

        请注意,您要调用的方法应该是虚拟的。

        更好的方法可以使用模板

        template<typename T>
        MyCallBack()
        {
            T Obj;
            Obj.perform();
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多