Singleton是設計模式中比較簡單的一個。園中的朋友們應該都很熟悉了。前段時間參加xxx外企的面試,和面試官討論C++的時候正好寫了一個。當時由於在有些地方考慮不太周全,代碼出現了一些疏漏。不過最終寫出了合格的實現。
Singleton模式
要求:
1、保證類只有一個實例
2、實例只能由類自身構造
3、必須為其他所有對象提供這一對象以訪問。
由此,我們畫出Singleton模式的結構圖如下:
根據要求,類實例只能由自身構造,因此必須要控制構造函數(默認構造函數和拷貝構造函數)的訪問權限(這裡不考慮繼承的問題)。
[cpp]
class Singleton{
private:
Singleton();
Singleton(Singleton &t);
};
class Singleton{
private:
Singleton();
Singleton(Singleton &t);
};
第一條,要求類只能有一個實例,因此必須防止客戶出現拷貝或者復制的情況。
[cpp]
class Singleton{
private:
Singleton();
Singleton(Singleton &t);
Singleton& operator= (Singleton &rhs);
};
class Singleton{
private:
Singleton();
Singleton(Singleton &t);
Singleton& operator= (Singleton &rhs);
};
最終實現如下:
[cpp]
class Singleton{
public:
Singleton *Instance();
private:
static Singleton *instance;
Singleton();
Singleton(Singleton &t);
Singleton& operator =(Singleton& rhs);
};
Singleton* Singleton::instance = null;
Singleton* Singleton::Instance{
if(instance == null){
instance = new Singleton();
}
return instance;
}
class Singleton{
public:
Singleton *Instance();
private:
static Singleton *instance;
Singleton();
Singleton(Singleton &t);
Singleton& operator =(Singleton& rhs);
};
Singleton* Singleton::instance = null;
Singleton* Singleton::Instance{
if(instance == null){
instance = new Singleton();
}
return instance;
}
在上面的代碼中,客戶需要通過下面的方式取得單例對象
[cpp]
Singleton *ps = Singleton::Instance();
Singleton *ps = Singleton::Instance();
因為函數返回了一個對象的指針,如果客戶失誤調用delete操作符,則很容易出現錯誤甚至程序崩潰。因此可以修改Singleton::Instance()的實現:
[cpp]
class Singleton{
public:
Singleton *Instance();
private:
Singleton();
Singleton(Singleton &t);
Singleton& operator =(Singleton& rhs);
};
Singleton* Singleton::Instance{
static Singleton instance;
return &instance;
}
class Singleton{
public:
Singleton *Instance();
private:
Singleton();
Singleton(Singleton &t);
Singleton& operator =(Singleton& rhs);
};
Singleton* Singleton::Instance{
static Singleton instance;
return &instance;
}
這樣更加安全,也體現了延遲創建的原則。
多態的實現
比較簡單而且好用的方法是使用模板。
[cpp]
template<class T>
class Singleton{
public:
T* Instance(){ static T t; return &t; }
private:
Singleton();
Singleton(Singleton&);
Singleton& operator=(Singleton&);
};
template<class T>
class Singleton{
public:
T* Instance(){ static T t; return &t; }
private:
Singleton();
Singleton(Singleton&);
Singleton& operator=(Singleton&);
};
在定義C++類時,編譯器會為我們自動創建一些函數(構造,析構,賦值操作符等),並且默認訪問權限為public,如果不希望客戶調用它,應該明確避免使用默認的實現,手動定義並限制其訪問權限(Effective C++中的設計原則),在這個例子中得到了非常好的應用。