用什么設計模式或其他技術手段解決如下代碼重復的問題?


先有3個類,每個類都有多個方法,意義相同的方法比如"a()",它們在各自的類中具體代碼稍有不同。這3個類一經投入生產就很少改動,偶爾可能會在各別類中加一些方法,比如添加class1.x()。
class1.a();
class1.b();
class1.c();

class2.a();
class2.b();
class2.w();

class3.a();
class3.t();
class3.w();

然后有在另一個具體使用的類中,有個方法總匯:
public void app.a(哪個類)
{
  switch(哪個類)
  {
     case "class1":
         class1.a();
     case "class2":
         class2.a();
     case "class3":
         class3.a();
  }
}

public void app.b(哪個類)
{
  switch(哪個類)
  {
     case "class1":
         class1.b();
     case "class2":
         class2.b();
  }
}

最后在main方法中,只需要使用app類中的方法總匯就可以了:
void main()
{
app.a("class2");
app.b("class1");
app.w("class2");
}

問題是:
app類中的方法太多,而每一個方法有相當有規律,使用那種設計模式或其他什么技術,可以使app類更簡化、更高效?

37 个解决方案

#1


繼承 和 重載

#2


多態呀!
你看到這種 
    case "class1":
         class1.a();
     case "class2":
         class2.a();
     case "class3":
東西很明顯應該用多態來處理啊。。

#3


太泛泛了,請給點提示好不好?

#4


adintr(www.adintr.com):
多態我學了,可不好意思,不會生搬硬套。
就按我舉的例子,可否給點代碼片斷看看?

#5


工廠模式

#6


仍舊一團霧水~  :(
Please Show me your code.

#7


class IApp{
  virtual void a() = 0;
  virtual void b() = 0;
};

class Class1 : public IApp
{
   void a(){};
   void b(){};
};

class Class2 : public IApp
{
  void a(){};
  void b(){};
};

class App
{
  static void a(IApp& c)
  {
   c.a();
  }

  static void b(IApp& c)
  {
   c.b();
  }
};

int main()
{
   Class1 c1;
   Class2 c2;
   App::a(c1);
   App::b(c1);
   App::a(c2);
   App::b(c2);
}

#8


@adint:
你的方法我看了,真的很不錯!有點不太適合我的應用,但凡要加方法,就需要全部在IApp借口中預先添加。好像耦合度有點高~

@ronlyxuyang , @bruceteen:
你按你的思路給個例子好嗎?pls.

#9


#include <iostream.h>

class Class1
{
public: 
void A()
{ cout << "Class1::A()" << endl; }
 
         void B()
         { cout << "Class1::B()" << endl; }
};

class Class2
{
public:
void A()
{ cout << "Class2::A()" << endl; }

         void B()
         { cout << "Class2::B()" << endl; }
};

class Class3
{
public:
void A()
{ cout << "Class3::A()" << endl; }
};

class App
{
public:
template<class T>
void A()
{
T t;
t.A();
}
};

int main()
{
App app;

app.A<Class1>();
         app.B<Class2>();

return 0;
}
==========
輸出:
Class1::A()
Class2::B()

#10



==================================================
但凡要加方法,就需要全部在IApp借口中預先添加。好像耦合度有點高~
==================================================

這怎么能是"耦合度有點高?"
看你要加的是什么樣的方法,如果是通用的就加到IApp中否則就加到派生類中.
這就是多態.

#11


路過。。感覺還是adintr的方法 適合你 的描述啊。。

#12


靜多態(模塊)和動多態(派生虛函數重寫)都行,

#13


用visitor模式,可以對各個類(class1,class2...)動態添加方法,尤其適用於各個類(class1,class2...)已經穩定。

代碼示例:
class base
{
public:
virtual void accept(visitor* v);
base()
{
};
};

class A:public base
{
public:
A(){};
void accept(visitor* v)
{
v->visitA(this);
}
};

class B:public base
{
public:
B(){};
void accept(visitor* v)
{
v->visitB(this);
}
};


class visitor
{
public:
virtual void visitA(base* baseA);
virtual void visitB(base* baseB);
protected:
visitor();
};

//定義A類和B類中的a()方法
class visitMethodA:public visitor
{
public:
void visitA(base* baseA)
{
};
void visitB(base* baseB)
{

};
visitMethodA(){};
};



void main()
{
//想調用A中的a()方法?
A aInstance;
visitor* vA = new visitMethodA();

aInstance.accept(vA);

}

#14


感覺用工廠方法模式能解決

#15


class App
{
public:
    template<typename T> void call_a(T& t)
    {
       t.a();
     }
    template<typename T> void call_b(T& t)
    {
       t.b();
     }
    template<typename T> void call_c(T& t)
    {
       t.b();
     }
};

class Class1
{
   public:
        void a(){}
};
class ClassAB
{
   public:
        void a(){}
        void b(){}
};
class ClassBC
{
   public:
        void b(){}
        void c(){}
};

void main()
{
    App app;
    ClassAB ab;
    app.call_a(ab);
    app.call_b(ab);
    ClassBC bc;
    app.call_b(bc);
    app.call_c(bc);
}

#16


代碼要求不是很全,但也可以看個大概了。這種方式用模板來實現是最方便的了。
利用模板,可以使不同的類協同工作。
如你給的代碼中,class a1,2,3 各不相同,但都有一個相同的名字的函數a  ,可以這樣做

class a1
{
void a();
void b();
};
class a2
{
void a();
void c();
};
class a3
{
void a();
void d();
};
template<typename T > 
void A()
{
T t;
t.a();
}
調用時使用A<a1>()  調用 a1的a
A<a2>()  調用 a2的a
A<a3>()  調用 a3的a 
這時候最好不要用繼承來實現,因為繼承首先使類層次變得復雜。其次,模板是在編譯期選擇你的函數的,比你的if-else更快!
在模式中這應該是策略模式

#17


使用d的時候呢,這是還必須對那個類有d()很清楚嗎?
封裝性不好了吧

#18


各位踴躍發言我真是太感動了,一下看這么多的東西,還要慢慢接受,我先分析分析,先謝過各位了!

#19


strategy不合適,用observe。

#20


up

#21


用一個抽象類做接口,把所有接口放到里面

#22


典型的創建型模式,工廠模式比較合適

#23


用多態,或者叫做模版方法模式。  
    實現類是哪一個,就多態調用哪個具體的實現方法。
這樣,就不需要switch和動態類型轉換了。

#24


為什么要用類名作為參數呢?不可以用其它的嗎?
比如如果是窗口類的話,不同的窗口風格用DWORD類型區別並相應的new之。。

如果實在是必須用類名作為參數..這個要涉及到RTTI,可以參考MFC的實現。。。

#25


支持一下 visual4825()  的方法
用模版最好

#26


應該考慮visitor模式,
確切的說是ACV(無環的Visitor模式),使用多繼承+動態類型轉換+基本的Visitor模式,ACV可以自由配置Visitor(通過多繼承),添加一個新的方法只要增加一個新的父類,而且不會對Visitor類有一致性要求。

#27


應該考慮visitor模式,
確切的說是ACV(無環的Visitor模式),使用多繼承+動態類型轉換+基本的Visitor模式,ACV可以自由配置Visitor(通過多繼承),添加一個新的方法只要增加一個新的父類,而且不會對Visitor類有一致性要求。
=================================================================================

不錯。我也贊同。不過visitor類很多情況下要訪問類的內部數據成員,必須得聲明成friend class,而且在子類中也要同樣聲明、有點麻煩!

#28


問題是:
app類中的方法太多,而每一個方法有相當有規律,使用那種設計模式或其他什么技術,可以使app類更簡化、更高效?
各位都沒有看清楚摟住的問題,不管用模板也好,Visito模式也好,並不能使app類更簡潔。
只是變化容易了而已

#29


class Base{
};

class Class1 : public Base
{
  public:
     void a(){}
     void b(){};
     void c(){};
};

class Class2 : public Base
{
  public:
     void a(){}
     void b(){};
     void c(){};
};
class Class3 : public Base
{
  public:
     void a(){}
     void b(){};
     void c(){};
};

class App
{
public:
   typedef void(Base::*FunType)();
   struct FunItem
   { 
       Base * obj;
       FunType fun;       
   };
   typedef std::map<std::string,FunType> MapType;
   MapType mapping_;

   void Registr(const std::string & className,const std::string & method,FunType fun , Base * obj)
   {
        FunItem item = {obj,fun};
        mapping_.insert(MapType::value_type(className + method,item));
   }   
   
   void Invoke(cosnt std::stirng & className,const std::string & method)
   {
        typename MapType::iterator it =mapping_.find(className + method);
        if( it != mapping_.end())
        {
             FunItem & item = it->second;
             (item.obj->*fun)();
        } 
   }
};
 這個應該是你想要的吧!





#30


顯然是Decorator模式嗎,運行期決定方法,鑒定完畢

#31


學習,好帖呀!!

#32


工廠模式不能解決動態添加函數的問題

#33


同意樓上的。對於比較穩定的類層次結構,而需要添加功能的,使用visitor模式。這是visitor模式的初喚

#34


好帖!!!

#35


visitor模式相對比較適合,具體情況可以復合其他的模式

#36


多態。 使用參數回調模式。
    使用接口或者抽象類。  各個具體類提供具體的實現方法。
public void app.a(基類或接口class)
{
   直接調class.a();
   不用判斷對象是那個具體實現類的實例。
}

#37


剛看了所有的回復,汗一下,沒一個人和我想法一樣。。。為什么不這樣做呢,就一個典型的接口設計問題

class IA
{
virtual a () = 0;
};

class IB
{
virtual b () = 0;
};

class IW
{
virtual w () = 0;
};

class C1 : public IA, IB
{
a ();
b ();
c (); //C1 specific method
};

class C2 : public IA, IB, IW
{
a ();
b ();
w ();
};

class C3 : public IA, IW
{
a ();
w ();
t ();
};

class App
{
a (IA &A) { A.a(); }
b (IB &B) { B.b(); }
w (IW &W) { W.w(); }
};


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com