面向對象設計的幾個基本原則和單例模式

本文是根據劉偉老師《設計模式的藝術》一書和網上資料整理而成,僅供學習交流之用。

一 設計原則
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定義爲私有的,就是防止在其他地方濫用。

發佈了21 篇原創文章 · 獲贊 17 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章