2016-09-26 12 views
-1

私はFactory Patternアプローチに関して多くのことを読んできましたが、スイッチのケースに基づいて実行時に目的の製品を返す静的メソッドが工場にあるようですが、これはOpenに違反しているようです新しい製品が登場するたびに、工場クラスを変更して必要な変更を加える必要があるため、原則を厳守してください。工場パターンに対する正しいアプローチは何ですか?

以下は、工場のパターンに沿っていると思いますが、このアプローチが正しいかどうかわかりません。基本的に私は、クライアントが必要な工場のタイプを知っていると思っています。それに基づいて、工場だけで扱う製品を手に入れます。

これが正しいアプローチかどうか、より良いもの。工場出荷時にコード更新を減らすために

#include "iostream" 
#include "memory" 
using namespace std; 

class AbstractDog{ 
    public: 
     virtual void bark(void) = 0; 
     AbstractDog(){cout << "AbstractDog created"<<'\n';} 
     virtual ~AbstractDog(){cout << "AbstractDog destroyed"<<'\n';} 
}; 

class chiwawa : public AbstractDog{ 
    public: 
     void bark(void){ 
      cout << "bark like chiwawa"<<'\n'; 
     } 
     chiwawa(){cout << "chiwawa created"<<'\n';} 
     virtual ~chiwawa(){cout << "chiwawa destroyed"<<'\n';} 
}; 

class alsatian : public AbstractDog{ 
    public: 
     void bark(void){ 
      cout << "bark like alsatian"<<'\n'; 
     } 
     alsatian(){cout << "alsatian created"<<'\n';} 
     virtual ~alsatian(){cout << "alsatian destroyed"<<'\n';} 
}; 


class AbstractDogFactory{ 
    public: 
     virtual AbstractDog* getDog(void) = 0; 
     AbstractDogFactory(){cout << "AbstractDogFactory created"<<'\n';} 
     virtual ~AbstractDogFactory(){cout << "AbstractDogFactory destroyed"<<'\n';} 
}; 

class smallDogFactory : public AbstractDogFactory{ 
    public: 
     virtual AbstractDog* getDog(void){ 
      return new chiwawa; 
     } 
     smallDogFactory(){cout << "smallDogFactory created"<<'\n';} 
     virtual ~smallDogFactory(){cout << "smallDogFactory destroyed"<<'\n';} 
}; 

class bigDogFactory : public AbstractDogFactory{ 
    public: 
     virtual AbstractDog* getDog(void){ 
      return new alsatian; 
     } 
     bigDogFactory(){cout << "bigDogFactory created"<<'\n';} 
     virtual ~bigDogFactory(){cout << "bigDogFactory destroyed"<<'\n';} 
}; 


int main() { 
    auto_ptr<AbstractDogFactory> m_ptr_fact(new bigDogFactory); 
    auto_ptr<AbstractDog>  m_ptr_dog(m_ptr_fact->getDog()); 
    m_ptr_dog->bark(); 
    return 0; 
} 
+1

まあ、確かに、あなたは、各ターゲット・タイプの工場のタイプを持つことができますが、それは問題には対処していません。間接的なレイヤーを追加するだけです。あなたの3番目の犬のタイプはどうですか? –

+0

私は3番目の犬が私は静的なファクトリメソッドのためのちょうど私のポイントthatsオープンクローズの原則に違反する新しいケースステートメントを書く必要があります。 –

+0

私の謝罪:私はあなたの質問を誤解しました。はい、新しいタイプが追加されると、工場を修正する必要があります。そして、はい、それはいくつかの**ガイドライン**に違反する可能性があります。 –

答えて

0

一つの方法は、(std::mapがあまりにも十分でしょう)関数ポインタをルックアップテーブルを使用することです。

コードは、キーをテーブルから検索し、作成されたインスタンスへのポインタを返す関数へのポインタを実行(参照)します。

新しいタイプの犬を追加するときは、データテーブルを更新します。ただし、dogインスタンスへのポインタを返す関数を記述する必要があります。工場が改造されます。しかし、ルックアップテーブルの基本的な検索機能は変更する必要はありません。

編集1:
例:

typedef (Abstract_Dog *) (*Dog_Creator_Func_Pointer)(); 
struct Table_Entry 
{ 
    const char * dog_name; 
    Dog_Creator_Func_Pointer p_creator; 
}; 
// Forward references 
Abstract_Dog * Create_Greyhound(); 
Abstract_Dog * Create_Bulldog(); 
//... 
static const Table_Entry creators[] = 
{ 
    {"greyhound", Create_Greyhound}, 
    {"bulldog", Create_Bulldog}, 
    //... 
}; 
static const unsigned int creator_quantity = 
    sizeof(creators)/sizeof(creators[0]); 

//... 
for (unsigned int i = 0; i < creator_quantity; ++i) 
{ 
    if (dog_name == creators[i].dog_name) 
    { 
    return (*creators[i].p_creator)(); 
    } 
} 
return nulptr; 
+0

if(dog_name == creators [i] .dog_name)は、私が言っていたスイッチケースの仕事をします。あなたがあなたのテーブルを変更する必要がある3番目の犬を追加するには、それはちょっと開いた終わりの原理に従って間違っていると感じます。 –

+0

オープンクローズの原則に違反することなくテーブルを更新するにはどうすればよいですか?原則をあまりにも真剣に考えているかもしれません。 –

関連する問題