一個目標:管理變化,提高複用
掌握設計模式一個核心目標:管理變化,提高複用。在使用設計模式中發現並沒有實現複用,這就和設計初衷相違背了,說明代買寫的不好。
兩種手段:分解VS.抽象
在程式碼設計中,該開始想要怎樣物件導向先要分解,比如這是梨,這是蘋果,這是香蕉建立這楊分解的思維,知道它們不同。但是呢我們很快建立抽象的思維,知道這一類都歸屬水果,然後就可以在思維管理裡面或程式管理裡面針對抽象進行統一的管理,比如水果有哪些功能的特徵。
八大原則
- 依賴倒置原則(DIP)
- 高層模組(穩定)不應該依賴於低層模組(變化),二者都應該依賴於抽象(穩定) 。
- 抽象(穩定)不應該依賴於實現細節(變化) ,實現細節應該依賴於抽象(穩定)。
- 開放封閉原則(OCP)
- 對擴充套件開放,對更改封閉。
- 類模組應該是可擴充套件的,但是不可修改。
- 單一職責原則(SRP)
- 一個類應該僅有一個引起它變化的原因。
- 變化的方向隱含著類的責任。
- Liskov 替換原則(LSP)
- 子類必須能夠替換它們的基類(IS-A)。
- 繼承表達型別抽象。
- 介面隔離原則(ISP)
- 不應該強迫客戶程式依賴它們不用的方法。
- 介面應該小而完備。
- 優先使用物件組合,而不是類繼承
- 類繼承通常為“白箱複用”,物件組合通常為“黑箱複用”。
- 繼承在某種程度上破壞了封裝性,子類父類耦合度高。
- 而物件組合則只要求被組合的物件具有良好定義的介面,耦合度低。
- 封裝變化點
- 使用封裝來建立物件之間的分界層,讓設計者可以在分界層的
- 一側進行修改,而不會對另一側產生不良的影響,從而實現層次間的鬆耦合。
- 針對介面程式設計,而不是針對實現程式設計
- 不將變數型別宣告為某個特定的具體類,而是宣告為某個介面。
- 客戶程式無需獲知物件的具體型別,只需要知道物件所具有的介面。
- 減少系統中各部分的依賴關係,從而實現”高內聚、鬆耦合"的型別設計方案。
重構技法
- 靜態 → 動態
- 早繫結→ 晚繫結
- 繼承→ 組合
- 編譯時依賴→ 執行時依賴
- 緊耦合→ 鬆耦合
從封裝變化角度對模式分類
C++ 物件模型
幾乎所有模式都歸屬第三種結構。繼承和組合在C++記憶體模型上沒有太大的區別,所以慎用繼承,優先組合,不過是帶指標的組合,如果是第二種會發生物件切割,而用指標更靈活,還可以指向它的子類。從耦合性來看,前兩種是緊耦合,第三種鬆耦合。
關注變化點和穩定點
設計模式的宗旨是:管理變化,提高複用。如果是所有都是變化的或穩定的,那用設計模式也沒有意義,設計模式是在管理變化實現穩定與變化隔離。
什麼時候不用模式
- 程式碼可讀性很差時
- 需求理解還很淺時
- 變化沒有顯現時
- 不是系統的關鍵依賴點
- 專案沒有複用價值時
- 專案將要釋出時
經驗之談
- 不要為模式而模式
- 關注抽象類&介面
- 理清變化點和穩定點
- 審視依賴關係
- 要有Framework和Application的區隔思維
- 良好的設計是演化的結果
設計模式成長之路
- “手中無劍,心中無劍”: 見模式而不知
- “手中有劍,心中無劍”: 可以識別模式,作為應用開發人員使用模式
- “手中有劍,心中有劍”: 作為框架開發人員為應用設計某些模式
- “手中無劍,心中有劍”: 忘掉模式,只有原則