2011-10-20 62 views
1

我目前使用下面這個簡單的單例類:辛格爾頓模板設計問題

template<class T> 
class singleton 
    : boost::noncopyable 
{ 
public: 
    static T& get_instance() 
     { 
      assert(sm_instance != nullptr); 
      return *static_cast<T*>(sm_instance); 
     } 

protected: 
    singleton() 
     { 
      assert(sm_instance == nullptr); 
      sm_instance = this; 
     } 
    virtual ~singleton() 
     { 
      assert(sm_instance != nullptr); 
      sm_instance = nullptr; 
     } 

private: 
    static singleton<T>* sm_instance; 
}; 

template<class T> singleton<T>* singleton<T>::sm_instance = nullptr; 


class example_one 
    : public singleton<example_one> 
{ 
    static example_one instance; 
}; 

example_one example_one::instance; 


class example_two 
    : singleton<example_two> 
{ 
    static example_two instance; 
}; 

example_two example_two::instance; 


// Usage: 
example_one& x = example_one::get_instance(); 
example_two& y = example_two::get_instance(); // not accessible because 'example_two' uses 'private' to inherit from 'singleton<T>' 

不過,我想調整一些東西。我不喜歡那get_instance()被繼承到派生類。

我願做這樣的事情(非工作代碼):

template<class T> 
T& get_singleton(); 

template<class T> 
class singleton 
{ 
    friend T& get_singleton() 
     { 
      assert(sm_instance != nullptr); 
      return *static_cast<T*>(sm_instance); 
     } 
} 

// Usage: 
example_two& x = get_singleton<example_two>(); 
+0

如果你能避免以任何方式,不使用單身 - http://stackoverflow.com/questions/1392315/problems-with-singleton-pattern –

+0

您的代碼不很有道理。第一個例子檢查它的實例字段是否爲空,在CONSTRUCTOR(爲什麼?),然後析構函數更糟。你的析構函數應該刪除sm_instance,或者根本不需要析構函數。在析構函數內部設置一個instacne字段爲空也是毫無意義的。 –

+0

@ AngelO'Sphere - 我認爲你應該再次閱讀代碼並思考它。 – 0xbadf00d

回答

0

如果你要使用一個模板函數,爲什麼與基類的麻煩:

template<typename T> 
T& getInstance() 
{ 
    static T instance; 
    return instance; 
} 

class example_one: boost::noncopyable 
{ 
     example_one() {} // Note private construtor 
     friend example_one& getInstance<example_one>(); 
}; 

class example_two: boost::noncopyable 
{ 
     example_two() {} 
     friend example_two& getInstance<example_two>(); 
}; 
+0

然後我的方法就不那麼靈活了。你需要一個'friend'聲明,一個私有拷貝構造函數和賦值操作符,並且你不能將編譯時間常量傳遞給'class'的構造函數。 – 0xbadf00d

+0

不,我不會這樣做(因爲你不會在我的代碼中找到singeltons)。但是你的論點都是有缺陷的。 1)它是一個singelton,你不需要傳遞任何東西給構造函數,只有一個,因此你所有的初始化都在構造函數中完成,你不需要傳遞任何東西。 2)所有singelton需要私有構造函數/拷貝構造函數和賦值運算符。 3)我的班級有一行額外的代碼一個朋友。你定義了一個不必要的鍋爐板子類。我想你會發現我的整潔和更可維護。即使singelton從一開始就是一個完全不好的主意。 –

+0

如果我打算建立一個單身人士,我會使用經典的Myers Singleton。我這樣做是因爲你試圖推廣樣板。 –

0

的由Andrei Alexandrescu推廣的解決方案使用了一種不同的技術,與此相比,它有幾個優點(其中一個是你想要做的調整)。它可以在http://loki-lib.cvs.sourceforge.net/loki-lib/loki/include/loki/Singleton.h?view=markup上找到,但是你可能想要下載整個庫(loki),或者如果你不需要這些附加組件,可以將它清理一下。接口就變成了:

typedef Loki::SingletonHolder< SomeType > SomeTypeSingleton; 
SomeTypeSingleton::Instance(); // Access the single instance