GeekBand C++設(shè)計模式 第一周

1.設(shè)計模式簡介

課程目標(biāo)

  • 松耦合設(shè)計思想
  • 面向?qū)ο笤O(shè)計原則
  • 重構(gòu)技法改善設(shè)計
  • GOF核心設(shè)計模式

設(shè)計模式

  • 不斷重復(fù)發(fā)生的問題
  • 解決方案的核心
  • 重復(fù)使用

面向?qū)ο螅?/h4>
  • 向下,如何把握機(jī)器底層從微觀理解對象構(gòu)造
    • 語言構(gòu)造
    • 編譯轉(zhuǎn)換
    • 內(nèi)存模型
    • 運行時機(jī)制
  • 向上:如何將我們周圍的世界抽象為程序代碼
  • 面向?qū)ο?/li>
  • 組件封裝
  • 設(shè)計模式
  • 架構(gòu)模式

深入理解面向?qū)ο螅?/h4>
  • 向下:三大面向?qū)ο髾C(jī)制
    • 封裝,隱藏內(nèi)部實現(xiàn)
    • 繼承,復(fù)用現(xiàn)有代碼
    • 多態(tài),改寫對象行為
  • 向上:深刻把握面向?qū)ο髾C(jī)制所帶來的抽象意義,理解如何使用這些機(jī)制來表達(dá)現(xiàn)實世界,掌握什么是“好的面向?qū)ο笤O(shè)計”

軟件設(shè)計復(fù)雜的根本原因:變化

  • 客戶需求
  • 技術(shù)平臺
  • 開發(fā)團(tuán)隊
  • 市場環(huán)境
  • ...

解決問題的思維模型:

  • 分解:將大問題分解為多個小問題,將復(fù)雜問題分解為多個簡單的問題(C語言為代表)
  • 抽象:由于不能掌握全部的復(fù)雜對象,我們選擇忽視它的非本質(zhì)細(xì)節(jié)而去處理泛化和理想化了的對象模型
什么是好的軟件設(shè)計?軟件設(shè)計的金科玉律:復(fù)用!

2.面向?qū)ο笤O(shè)計原則

變化是復(fù)用的天敵!面向?qū)ο笤O(shè)計最大的優(yōu)勢在于:抵御變化!

重新認(rèn)識面向?qū)ο螅?/h4>
  • 隔離變化:能將變化所帶來的影響減到最小。
  • 各司其職:面向?qū)ο蟮姆绞綇?qiáng)調(diào)個各類的“職責(zé)”,新增加的類不會影響原有類。
  • 對象是什么?
    • 語言:對象封裝了代碼和數(shù)據(jù)。
    • 規(guī)格:對象是一系列可被使用的公共接口。
    • 概念:對象是某種擁有責(zé)任的抽象。

面向?qū)ο笤O(shè)計原則:

設(shè)計原則比設(shè)計模式更為重要,在發(fā)展的過程中,設(shè)計模式可能在變,但是設(shè)計模式依賴于設(shè)計原則,設(shè)計原則是評判設(shè)計模式的標(biāo)準(zhǔn)。

依賴導(dǎo)致原則(DIP)

  • 高層模塊(穩(wěn)定)不應(yīng)該依賴于低層模塊(變化),二者都應(yīng)該依賴于抽象(穩(wěn)定)。
  • 抽象(穩(wěn)定)不應(yīng)該依賴于實現(xiàn)細(xì)節(jié)(變化),實現(xiàn)細(xì)節(jié)能改依賴于抽象(抽象)。

開放封閉原則(OCP)

  • 對擴(kuò)展開放,對更改封閉
  • 類模塊應(yīng)該是可擴(kuò)展的,但是不可修改。

單一職責(zé)原則(SRP)

關(guān)于類的職責(zé),思考時必須慎之又慎!

  • 一個類應(yīng)該僅有一個引起它變化的原因。
  • 變化的方向隱含著類的責(zé)任。

Liskov替換原則(LSP)

  • 子類必須能夠替換他們的基類(IS-A)。
  • 繼承表達(dá)類型抽象。

接口隔離原則(ISP)

  • 不應(yīng)該強(qiáng)迫客戶程序依賴他們不用的方法。
  • 接口應(yīng)該小而完備。

優(yōu)先使用對象組合,而不是類繼承

  • 類繼承通常為“白箱復(fù)用”,對象組合通常為“黑箱復(fù)用”。
  • 繼承在某種程度上破壞了封裝性,子類父類耦合度高。
  • 對象組合則只要求被組合的對象具有良好定義的接口,耦合度底。

封裝變化點

  • 使用封裝創(chuàng)建對象之間的分界層,讓設(shè)計者可以在分界層的一側(cè)進(jìn)行修改,而不會對另一側(cè)產(chǎn)生不良的影響,從而實現(xiàn)層次間的松耦合。

針對接口編程,而不是針對實現(xiàn)編程

  • 不將變量類型聲明為某個特定的具體類,而是聲明為某個接口。
  • 客戶程序無需獲知對象的具體類型,只需要知道對象所具有的接口。
  • 減少系統(tǒng)中各部分的依賴關(guān)系,從而實現(xiàn)“高內(nèi)聚,松耦合”的類型設(shè)計方案。

面向接口設(shè)計,產(chǎn)業(yè)強(qiáng)盛的標(biāo)志:接口標(biāo)準(zhǔn)化

GOF-23模式分類

從目的

  • 創(chuàng)建型(Creational)
  • 結(jié)構(gòu)型(Structural)
  • 行為型(Behavioral)

從范圍(實現(xiàn)手段)

  • 類模式(類和子類的靜態(tài)關(guān)系)(繼承方案)
  • 對象模式(對象間的動態(tài)關(guān)系)(組合方案)

從封裝變化角度對模式分類:

重構(gòu)獲得模式 Refactoring to Patterns

  • 應(yīng)對變化,提高復(fù)用
  • 發(fā)現(xiàn)變化,在變化點處應(yīng)用設(shè)計模式。什么時候、什么地點應(yīng)用設(shè)計模式理解設(shè)計模式結(jié)構(gòu)本身更為重要
  • 設(shè)計模式應(yīng)用不宜先入為主。沒有一步到位的設(shè)計模式。

重構(gòu)關(guān)鍵技巧:

  • 靜態(tài) -> 動態(tài)
  • 早綁定 -> 晚綁定
  • 繼承 -> 組合
  • 編譯器依賴 -> 運行時依賴
  • 緊耦合 -> 松耦合

3.組件協(xié)作模式

  • 現(xiàn)代軟件專業(yè)分工之后的第一個結(jié)果是“框架與應(yīng)用程序的劃分”,“組件協(xié)作”模式通過晚期綁定,來實現(xiàn)框架與應(yīng)用程序之間的松耦合,是二者之間協(xié)作時常用的模式。
  • 典型模式
    • Template Method
    • Strategy
    • Observer/Event

Template Method

動機(jī)

  • 在軟件構(gòu)件過程中,對于某一項任務(wù),它常常有穩(wěn)定的整體操作結(jié)構(gòu),但是個個自步驟卻有很多改變的需求,或者由于固有的原因(比如框架與應(yīng)用之間的關(guān)系)而無法和任務(wù)的整體結(jié)構(gòu)同時實現(xiàn)。
  • 定義一個操作中的算法的骨架(穩(wěn)定),而將一些步驟延遲(變化)到子類中。Template Method使得子類可以不改變(復(fù)用)一個算法的結(jié)構(gòu)即可重定義(override重寫)該算法的某些特定步驟。

結(jié)構(gòu)

要點總結(jié)

  • Template Method模式是一種非常基礎(chǔ)性的設(shè)計模式,在面向?qū)ο笙到y(tǒng)中有著大量的應(yīng)用。使用虛函數(shù)的多態(tài)性為很多應(yīng)用程序框架提供了靈活的擴(kuò)展點,是代碼復(fù)用方面的基本實現(xiàn)結(jié)構(gòu)。
  • 除了可以靈活對子步驟的變化外,“不要調(diào)用我,讓我來調(diào)用你”的反向控制結(jié)構(gòu)是Template Method的典型應(yīng)用。
  • 在實現(xiàn)時,被Template Method調(diào)用的虛方法可以具有實現(xiàn),也可以沒有任何實現(xiàn)(抽象方法、純虛方法),但一般推薦將他們設(shè)置為protected方法。

Strategy

動機(jī)

  • 在軟件構(gòu)件過程中,某些對象使用的算法可能多種多樣,經(jīng)常改變,如果將這些算法都編碼到對象中,將會使對象變得異常負(fù)責(zé),而且有時候支持不適用的算法也是一個性能負(fù)擔(dān)。
  • 定義一系列算法,把他們一個個封裝起來,并且使他們可以相互替換(變化),該模式使得算法可獨立于使用它的客戶程序(穩(wěn)定)而變化(擴(kuò)展,子類化)。

結(jié)構(gòu)

要點總結(jié)

  • Strategy及其子類為組件提供了一系列可重用的算法,從而可以使得類型在運行時方便地根據(jù)需要在各個算法之間進(jìn)行切換。
  • Strategy模式提供了用條件判斷語句以外的另一種選擇,消除條件判斷語句,就是在解耦合。含有許多條件判斷語句的代碼通常都需要使用Strategy模式。
  • 如果Strategy對象沒有實例變量,那么各個上下文可以共享同一個Strategy對象,從而節(jié)省對象開銷。

Observer/Event

動機(jī)

  • 在軟件構(gòu)建過程中,我們需要為某些對象建立一種“通知依賴關(guān)系”——一個對象(目標(biāo)對象)的狀態(tài)發(fā)生改變,所有的依賴對象(觀察者對象)都將得到通知。
  • 定義對象間的一種一對多(變化)的依賴關(guān)系,以便當(dāng)一個對象(Subject)的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并自動更新。

結(jié)構(gòu)

要點總結(jié)

  • 使用面向?qū)ο蟮某橄螅琌bserver模式使得我們可以獨立地改變(改變時,兩者不相互影響)目標(biāo)與觀察者,從而使二者之間的依賴關(guān)系松耦合。
  • 目標(biāo)發(fā)送通知時,無需指定觀察者,通知會自動傳播。
  • 觀察者自己決定是否需要訂閱通知,目標(biāo)對象對此一無所知。
  • Observer模式是基于事件的UI框架中非常常用的設(shè)計模式,是MVC的一個重要組成部分。

最關(guān)鍵的是抽象的通知依賴關(guān)系。

4.單一職責(zé)

  • 在軟件設(shè)計中,如果責(zé)任劃分不清楚,使用繼承得到的結(jié)果往往都是隨著需求變化,子類急劇膨脹,同時充斥著很多重復(fù)代碼,這時候的關(guān)鍵是劃清責(zé)任。
  • 典型模式
    • Decorator
    • Bridge

Decorator 裝飾模式

動機(jī)

  • 在某些情況下,我們可能會“過度的使用繼承來擴(kuò)展對象的功能”,由于繼承為類型引入的靜態(tài)特性,使得這種擴(kuò)展方式缺少靈活性,并且隨著子類的增多,各種子類的組合會導(dǎo)致更多子類的膨脹。
  • 動態(tài)(組合)的給一個對象增加一些額外的職責(zé),就增加功能而言,Decorator模式比生成子類(繼承)更為靈活(消除重復(fù)代碼&減少子類個數(shù))。

結(jié)構(gòu)

要點總結(jié)

  • 通過組合而非繼承的手法,Decorator模式實現(xiàn)了在運行時動態(tài)擴(kuò)展對象功能的能力,可根據(jù)需要擴(kuò)展多個功能。
  • Decorator類在接口上表現(xiàn)為is-a Component的繼承關(guān)系,即Decorator類繼承了Component類的所有接口。但是在實現(xiàn)上又表現(xiàn)為has-a Component的組合關(guān)系,即Decorator類又使用了另一個Component類。(以后當(dāng)看到一個類,同時繼承和組合父類,那么很多時候就是使用了Decorator設(shè)計模式。
  • Decorator模式應(yīng)用的要點在于解決“主體類在多個方向上的擴(kuò)展功能”----即為“裝飾”

Bridge 橋模式

動機(jī)

  • 由于某些類型的固有的實現(xiàn)邏輯,使得它們具有連個變化的維度,乃至多個維度的變化。
  • 將抽象部分(業(yè)務(wù)功能)與實現(xiàn)部分(平臺實現(xiàn))分離,使它們可以獨立變化。

結(jié)構(gòu)

要點總結(jié)

  • Bridge模式使用“對象間的組合關(guān)系”解耦了抽象和實現(xiàn)之間固有的綁定關(guān)系,使得抽象和實現(xiàn)可以沿著各自的維度變化(子類)。
  • Bridge模式有時候類似于多繼承,但是多繼承方案往往未被單一職責(zé)原則,復(fù)用性較差。
  • Bridge模式的應(yīng)用一般在“兩個非常強(qiáng)的變化維度”,當(dāng)多于兩個的變化維度,可以使用Bridge的擴(kuò)展模式。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內(nèi)容