2016-09-26 49 views
-1

我一直在閱讀很多關於工廠模式方法的內容,並且在所有這些方法中,似乎都有一個工廠中的靜態方法,它基於switch-case在運行時返回所需的產品,但這似乎違反了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

哦,當然,你可以爲每個目標類型工廠類型,但這並不解決問題。它只是增加了一個間接層。你的第三種狗類型呢? –

+0

這就是我的靜態工廠方法的時候,當我有第三條狗時,我將不得不寫一個新的case語句,這違反了Open Close原則。 –

+0

我的歉意:我誤解了你的問題。是的,當新的類型被添加時,工廠必須被修改。而且,是的,這可能會違反**準則**。 –

回答

0

一種方法,以減少代碼更新一廠是用函數指針(一個std::map就足夠太)的查找表。

代碼將在表中搜索關鍵字,然後執行(deference)指向返回指向創建實例的指針的函數的指針。

添加新類型的狗時,您需要更新數據表。但是,您需要編寫一個函數來返回指向狗實例的指針;因此工廠被修改。但是,查找表的基本搜索功能不需要改變。

編輯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)做了我所說的switch case的工作,沒有要添加第三隻狗,你需要修改你的桌子,這有點感覺錯誤,按照開放式關閉原則。 –

+0

如何在不違反開放式關閉原則的情況下更新表格?你可能會認真對待這個原則。 –