2012-03-07 16 views
1

私はモデルビューアーキテクチャを持っています。モデルオブジェクトからビューオブジェクトを作成したいと思います。 ここに基本的な例があります。あなたはすべてのためのインタフェースを必要とするファクトリオブジェクトの型を指定する方法

class ModelA 
{ 
    ModelA(int a); 
} 

class ModelB : public ModelA 
{ 
    ModelB(int a,int b); 
} 

class ViewModelA 
{ 
    ViewModelA(ModelA* ma); 
} 

class ViewModelB : public ViewModelA 
{ 
    ViewModelB(ModelB* mb); 
} 

class ViewFactory 
{ 
    ModelA * createFromModel(ModelA *ma) 
    { 
      // Now what is the best way to store type ??? 
      // Used an integer and overload a static method getType() 
      // Or use an enum? 
      switch(ma.type) 
      { 

      } 
    } 
} 


int main(int argc, char *argv[]) 
{ 
    ModelA *ma = new ModelA(10); 
    ModelA *mb = new ModelB(10,11); 
    ViewFactory myFactory; 
    ViewModelA *va = myFactory.createFromModel(ma); 
    ViewModelB *vb = myFactory.createFromModel(mb); 
    //va should be a model of ViewModelA and vb a model of ViewModelB 
} 
+0

理由だけではなく、保存されたタイプとswitch文よりも、ここでの多型を使わないのでしょうか?あなたの 'createFromModel'関数は' ModelA'ポインタ上のメンバ関数を呼び出すだけで、適切な関数は多態的に選択されます。 –

答えて

4

私見では、あなたの質問や他の回答にコメントから、あなたもここVisitor patternを使用することができます。 これについて読むhereまたはhere

したがって、モデル階層にはVisitorが表示されます。 Visitorの責任は、訪問されたModelタイプの適切なViewオブジェクトを作成することです。

モデルタイプを保存/宣言する必要はありません。コード作業

は:もここに住ん:http://ideone.com/9A5bJ

#include <iostream> 



class Visitor{ 
public: 
    virtual ~Visitor(){} 
    virtual void visitModelA(class ModelA*) = 0; 
    virtual void visitModelB(class ModelB*) = 0; 
    //add visit functions for later defined models 

}; 





class View{ 
public: 
    virtual ~View(){} 
}; 

class ViewA : public View{ 
public: 
    ViewA(){ 
     std::cout << "Created ViewA\n"; 
    } 
}; 


class ViewB : public View{ 
public: 
    ViewB(){ 
     std::cout << "Created ViewB\n"; 
    } 
}; 








class Model{ 
public: 
    virtual ~Model(){} 

    virtual void Accept(Visitor* visitor) = 0; 

}; 

class ModelA:public Model{ 
public: 

    virtual void Accept(Visitor* visitor){ 
     visitor->visitModelA(this); 
    } 
}; 

class ModelB:public Model{ 
public: 
    virtual void Accept(Visitor* visitor){ 
     visitor->visitModelB(this); 
    } 
}; 






// ViewCreator can be made a private class of ViewFactory 
class ViewCreator : public Visitor{ 
public: 
    virtual void visitModelA(class ModelA*) { 
     _view = new ViewA(); 
    } 
    virtual void visitModelB(class ModelB*) { 
     _view = new ViewB(); 
    } 

    //add visit functions for later defined models 

    View* GetView(){ 
     return _view; 
    } 

private: 
    View* _view; 
}; 


class ViewFactory{ 
public: 
    static View* CreateViewFor(Model* model){ 
     ViewCreator viewCreator; 
     model->Accept(&viewCreator); 
     return viewCreator.GetView(); 
    } 

}; 


int main(){ 

    ModelA modelA; 
    View* viewA = ViewFactory::CreateViewFor(&modelA); 


    ModelB modelB; 
    View* viewB = ViewFactory::CreateViewFor(&modelB); 



} 
+0

私にはあまりにも多くの残虐行為のようです。私はモデルに訪問者へのリンクを維持する必要があるので、プラス私はモデルに余分なデータを追加する必要があります。おそらく – Anton

+0

。 Modelに余分なデータを保存する必要はなく、Accept関数()を追加する必要があります。 – fizzbuzz

+0

サンプルコードはこちらですhttp://ideone.com/9A5bJ – fizzbuzz

0

...列挙型(が、その後、彼らは拡張可能ではありません)、int型(しかし、めちゃくちゃ取得するために、その後は簡単):どのように私は私のモデルオブジェクトの種類を指定しない

タイプ:

class ModelIface 
{ 
} 
class ModelA : public ModelIface 
{ 
    ModelA(int a); 
} 

class ModelB : public ModelIface 
{ 
    ModelB(int a,int b); 
} 

class ViewIface 
{ 
} 
class ViewModelA : public ViewIface 
{ 
    ViewModelA(ModelIface* ma); 
} 

class ViewModelB : public ViewIface 
{ 
    ViewModelB(ModelIface* mb); 
} 

class ViewFactory 
{ 
    ViewIface * create(ModelIface *ma) 
    { 
      switch(ma.type) 
      { 
      case TYPE1: 
       return new ViewModelA(ma); 
      case TYPE2: 
       return new ViewModelB(ma); 
      default : 
       ; 
      } 
      return nullptr; 
    } 
} 

TYPE1とTYPE2がintかenumは無関係かどうか。

int main(int argc, char *argv[]) 
{ 
    ModelIface *ma = new ModelA(10); 
    ModelIface *mb = new ModelB(10,11); 
    ViewFactory myFactory; 
    ViewModelIface *va = myFactory.createFromModel(ma); 
    ViewModelIface *vb = myFactory.createFromModel(mb); 
    //va should be a model of ViewModelA and vb a model of ViewModelB 
} 
+0

タイプとしてenumを使用している場合は、(ModelInterfaceの)基本クラスに格納する必要があるため、モデル階層に新しいクラスを追加するたびにModelInterfaceを変更する必要があり、再コンパイルを恐れる長いです... – Anton

+0

@Antonいいえ、なぜあなたはそれをベースクラスに格納する必要がありますか?別のヘッダーに格納することができます.C++ 11では、厳密に型指定された列挙型を使用して前方宣言を列挙できます。 –

+0

私はMinGW gccがC++ 11のスタンドアールなのか分かりません。なぜか、私はenumの前方宣言を使うことができないと思います。 – Anton

関連する問題