2015-09-02 94 views
0

我想實現的是由在C++私有構造

  • 一個工廠類工廠模式工廠模式
  • 的抽象類與受保護的構造
  • 繼承類有私有構造函數和虛擬公共 析構函數。

我想確保

  • 沒有其他人比工廠不能創建任何實例
  • 如果一個新的繼承類的定義也不會要求對接口類,並已進行任何修改定義的繼承類。 Juts新類實現並添加到工廠類中創建方法。

我也不想爲每個繼承類編寫類似代碼(比如每個被繼承類的靜態工廠方法),並讓未來的開發人員爲工廠連接做很多工作。

即與pseduo代碼

class Factory; 

class Interface 
{ 
    protected: 
     Interface(){/*Do something*/}; 
    public: 
     virtual ~Interface(){/*Do something*/} 
    /*I wish I could do below and it is valid for all inherited 
    classes but friendship is not inherited in C++*/ 
    //friend Interface* Factory::create(Type) 
}; 

class InheritedA:public Interface 
{ 
    private: 
     InheritedA(){/*Do something*/}; 
    public: 
     virtual ~InheritedA(){/*Do something*/} 
    /*I dont want to do below two lines for every inherited class*/ 
    //friend Interface Factory::create(Type) 
    //public: Interface* factoryInheritedA(){return new InheritedA();} 
}; 

class InheritedB:public Interface 
{ 
    private: 
     InheritedB(){/*Do something*/}; 
    public: 
     virtual ~InheritedA(){/*Do something*/} 
}; 

class Factory 
{ 
    static Interface* create(Interface type)  
    { 
      switch(type) 
      { 
      case A: 
       return new InheritedA(); 
      case B: 
       return new InheritedB(); 
      default: 
       //exceptions etc 
      } 
    } 
} 

int main() 
{ 
    Interface* I = Factory::create(A/*or B*/); 
    return 0; 
} 

上面的代碼是我放出來的cloest。任何建議(C++的專業,不同的設計,...)都是值得歡迎的。

+8

你忘了寫一個問題。 – Lemonov

+2

爲什麼你需要這一切?聽起來像Javaesque。這可能是XY問題的一個例子。 – Shoe

+0

@UzorTuTuEjt我寫了我想要做的限制。我真的不明白爲什麼需要問句 – ataman

回答

0

你可以有一個模板功能:

template<typename Type> 
std::unique_ptr<Interface> make_interface() { 
    // exceptions etc.. 
} 

template<> 
std::unique_ptr<Interface> make_interface<InheritedA>() { 
    return std::make_unique<InheritedA>(); 
} 

template<> 
std::unique_ptr<Interface> make_interface<InheritedB>() { 
    return std::make_unique<InheritedB>(); 
} 

但我真的沒有看到這一切Javaesque樣板點。更不用說,你真的無緣無故地將編譯時信息(類型)轉換爲運行時信息(通過例外)。

與我只想去:在需要的時候

std::unique_ptr<Interface> ptr_a = std::make_unique<InheritedA>(); 
std::unique_ptr<Interface> ptr_b = std::make_unique<InheritedB>(); 

+0

模板特化可能會被兩個常規函數替代,對嗎? – JorenHeit

+0

@JorenHeit嗯,不,如果你想讓'make_interface '在'Type'不是'InheritedA'或'InheritedB'時引發異常。 – Shoe

+0

你爲什麼要這樣?我寧願有一個編譯器錯誤。 – JorenHeit

2

我不認爲這是一個好主意,但這裏有一個方法可以做到這一點。您可以創建一個只能由Factory創建的標籤類型,並使所有構造函數都具有該類型的參數。

class Factory; 

class Tag 
{ 
    Tag() {} 
    friend Factory; 
}; 

class Interface 
{ 
public: 
    Interface(Tag t) {} 
    virtual ~Interface() {} 
}; 

struct Impl1: public Interface 
{ 
    Impl1(Tag t): Interface(t) {} 
}; 

class Factory 
{ 
public: 
    Interface* makeInstance() 
    { 
     return new Impl1(Tag{}); 
    } 
}; 

void foo() 
{ 
    Impl1 i(Tag{}); 
} 

您將在foo()因爲Tag::Tag是民營得到一個編譯錯誤。

+0

至少它禁止其他人創建實例。這還不是一個解決方案,但可能是一個好的開始。謝謝。 – ataman

-1

使用Factory幾乎不是一個好習慣。我把它和Singleton一起算作反模式。在良好的設計中,classess不關心他們是如何創建的。在你的情況下,當在Factory中使用時,你如何使用自定義分配器創建你的類?在堆棧上?在共享內存中?在內存映射文件中?從緩衝區?到位?這在工廠中確實很難涵蓋,但不要絕望 - 簡單而優雅的解決方案將工廠拋棄!

+0

將工廠視爲反模式可能是非常罕見的觀點。我也無法追隨推理。據我所知,工廠的要點是將客戶端與創建相關對象分離開來,即客戶端不應該知道創建的內容或創建方式。它與創建的對象本身無關。正是爲了強制執行「classess不關心他們是如何被創造的」,你認爲這是優秀的設計。 – Jens

+0

@Jens,首先,「客戶不應該知道它是如何創建的」這個陳述是糟糕設計的同義詞。客戶需要能夠控制對象的創建方式。簡單地在堆中新出現的一切都已經過去了。例如,沒有性能低的應用程序(並且對任何使用C++的非性能critycal應用程序都很可惜)真的想用vanilla new來創建它們的對象。就如此容易。你需要爲分配器提供一個工廠,這是必須的。 Comm。大小限制了我的進一步寫作,但我的立場是堅定的 - 工廠完成工作的方式通常很糟糕。 – SergeyA

+0

我不認爲你明白我的觀點。假設我有一個類A,它使用了一些具有抽象接口B和子類C和D的類層次結構。在類A中,爲了可重用,我希望能夠自定義C和D中的哪一個(或一個新的實現X)被創建。如果我使用工廠,我可以做到這一點。我也可以通過實施另一家工廠來決定分配策略。 A類不知道如何創建。我認爲這是很好的設計,大多數人可能會同意。我也不知道如何在沒有工廠的情況下編寫可測試的代碼。 – Jens