本文是根據劉偉老師《設計模式的藝術》一書和網上資料整理而成,僅供學習交流之用。
一 設計原則
1 單一職責原則:一個類只負責一個功能領域中的相應職責,或者說一個類只有一個引起它變化的原因,簡單來說就是一個類不能承擔太多的職責。
2 開閉原則:一個軟件實體應當對擴展開放,對修改關閉,即軟件實體儘量在不修改原有代碼的情況下進行擴展。
3 里氏代換:所有引用基類的地方必須能透明的使用其子類的對象。在軟件中將一個對象替換成它的之類對象不會產生異常,但是反過來不成立。例如:小明喜歡動物,那小明一定喜歡狗,但是小明喜歡狗卻不一定喜歡所有動物。
4 依賴倒轉:抽象不應依賴於細節,細節應當依賴於抽象。即:要針對接口編程,而不是針對實現編程。
5 接口隔離:使用多個專門的接口,而不使用單一的總接口,即客戶端不應該依賴於那些它不需要的接口。
6 合成複用:儘量使用對象組合,而不是繼承來達到複用的目的。
7 迪米特法則:一個軟件應該儘可能的減少與其他實體發生互相作用。
二 軟件設計模式
1) 單例模式
確保一個類只有一個實例,而且自行實例化並向整個系統提供這個實例。該類稱爲單例類,它提供全局的訪問方法。比如操作系統只能啓動一個任務管理器。
C++單例模式
class CSingleton
{
private:
CSington(){} // 構造函數是私有的
static CSingleton * m_pInstance;
public:
static CSingleton * GetInstance(){
if(m_pInstance == NULL) {
m_pInstance = new CSingletion();
}
return m_pInstance;
}
}
用戶訪問唯一實例的方法只有GetInstance()成員函數,因爲構造函數是私有的。GetInstance()是懶惰實例化,即它的返回值是當這個函數首次被訪問的時候被創建的。
上面的代碼存在兩個問題:
1 m_pInstance指向的空間什麼時候釋放呢?
2 更嚴重的問題是,該實例的析構函數什麼時候執行?
有兩種方法可以解決上述問題:
1 程序結束的時候調用GetInstance(),並對返回的指針調用delete操作,但是這樣容易出錯,難以保證delete後不再調用GetInstance()函數。
2 程序結束的時候,系統會自動析構所有的全局變量,也會析構所有的靜態成員函數。所以在單例類中定義一個靜態成員變量,它的唯一工作就是析構單例類的實例。代碼如下:
class CSingleton()
{
private:
CSingleton():{}
static CSingleton * m_pInstance;
class CGarbo{
public:
~CGarbo(){ // 假如要在類的外部訪問該內嵌類,需要外圍類::內嵌類
if(CSingleton::m_pInstance){ // 注意內嵌類的使用格式
delete CSingleton::m_pInstance;
}
}
}
public:
static CSingleton * GetInstance(){
if(CSingleton::m_pInstance == NULL) {
m_pInstance = new CSingleton();
}
return m_instance;
}
}
將CGarbo定義爲私有的,就是防止在其他地方濫用。