C++設(shè)計(jì)模式第一周學(xué)習(xí)筆記——Boolan

C++設(shè)計(jì)模式是本周開始的一門全新的課程,在完成了第一周的學(xué)習(xí)之后,對C++設(shè)計(jì)模式有了一定的認(rèn)識和了解,因此有一些總結(jié)和心得在這里通過學(xué)習(xí)筆記的方式分享出來,筆記我是跟著老師在視頻中所講的內(nèi)容按照順序記錄的,也不能說是流水賬,對課程中的一些問題還是添加了自己的理解和分析,供也在學(xué)習(xí)C++的小伙伴用作學(xué)習(xí)交流,如有理解不到位的地方,歡迎批評指正。

在正式開始學(xué)習(xí)之前,首先明確本課程的目標(biāo):

1.理解松耦合設(shè)計(jì)思想

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

3.掌握重構(gòu)技法改善設(shè)計(jì)

4.掌握GOF核心設(shè)計(jì)模式

一開始看到課程目標(biāo)我也是云里霧里的,但是相信在今后幾周的學(xué)習(xí)中,我們肯定能達(dá)到這個(gè)學(xué)習(xí)目標(biāo)!

一.設(shè)計(jì)模式簡介

什么是設(shè)計(jì)模式呢?“每一個(gè)模式描述了一個(gè)在我們周圍不斷重復(fù)發(fā)生的問題,以及該問題的解決方案核心。這樣,你就能一次又一次地使用該方案而不必做重復(fù)勞動(dòng)?!倍覀兙褪且悦嫦?qū)ο鬄榛A(chǔ),主要學(xué)習(xí)掌握“好的面向?qū)ο笤O(shè)計(jì)”。因此我們必須將向下的底層思維和向上的抽象思維聯(lián)系起來,把握機(jī)器底層從微觀理解對象構(gòu)造,將我們周圍世界抽象為程序代碼。向下深入理解三大面向?qū)ο髾C(jī)制:封裝(隱藏內(nèi)部實(shí)現(xiàn))、繼承(復(fù)用現(xiàn)有代碼)、多態(tài)(改寫對象行為);向上深刻把握面向?qū)ο髾C(jī)制所帶來的抽象意義,掌握什么是“好的面向?qū)ο笤O(shè)計(jì)”。

軟件設(shè)計(jì)有其固有的復(fù)雜性,軟件設(shè)計(jì)復(fù)雜的根本原因在于“變化”,客戶需求的變化、技術(shù)平臺的變化、開發(fā)團(tuán)隊(duì)的變化、市場環(huán)境的變化… …通常,人們解決復(fù)雜性會(huì)用到兩種方法:一種是分解。這很好理解,將一個(gè)復(fù)雜的問題拆分成幾個(gè)簡單的問題,但是這種方法的缺點(diǎn)在于不是任何問題都適用且復(fù)用性差。第二種是抽象。由于不能掌握全部的復(fù)雜對象,我們選擇忽視它的非本質(zhì)細(xì)節(jié),而去處理泛化和理想化了的對象模型。一個(gè)好的設(shè)計(jì)軟件,一定是能夠復(fù)用的!變化是復(fù)用的天敵,面向?qū)ο笤O(shè)計(jì)最大的優(yōu)勢在于抵御變化!

二.面向?qū)ο笤O(shè)計(jì)原則(八大原則)

1.依賴倒置原則(DIP)

高層模塊(穩(wěn)定)不應(yīng)該依賴于低層模塊(變化),二者都應(yīng)該依賴于抽象(穩(wěn)定)。

抽象(穩(wěn)定)不應(yīng)該依賴于實(shí)現(xiàn)細(xì)節(jié)(變化),實(shí)現(xiàn)細(xì)節(jié)應(yīng)該依賴于抽象(穩(wěn)定)。

2.開放封閉原則(OCP)

對擴(kuò)展開放,對更改封閉。

類模塊應(yīng)該是可擴(kuò)展的,但是不可修改。

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

一個(gè)類應(yīng)該僅有一個(gè)引起它變化的原因。

變化的方向隱含著類的責(zé)任。

4.Liskov替換原則(LSP)

子類必須能夠替換它們的基類(IS-A)。

繼承表達(dá)類型抽象。

5.接口隔離原則(ISP)

不應(yīng)該強(qiáng)迫客戶程序依賴它們不用的方法。

接口應(yīng)該小而完備。

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

類繼承通常為“白箱復(fù)用”,對象組合通常為“黑箱復(fù)用”。

繼承在某種程度上破壞了封裝性,子類父類耦合度高。

而對象組合則只要求被組合的對象具有良好定義的接口,耦合度低。

7.封裝變化點(diǎn)

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

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

不將變量類型聲明為某個(gè)特定的具體類,而是聲明為某個(gè)接口。

客戶程序無需獲知對象的具體類型,只需要知道對象所具有的接口。

減少系統(tǒng)中各部分的依賴關(guān)系,從而實(shí)現(xiàn)“高內(nèi)聚、松耦合”的類型設(shè)計(jì)方案。

三.GOF-23種設(shè)計(jì)模式分類

1.從目的來看分為:

創(chuàng)建型(Creational)模式:將對象的部分創(chuàng)建工作延遲到子類或者其他對象,從而應(yīng)對需求變化為對象創(chuàng)建時(shí)具體類型實(shí)現(xiàn)引來的沖擊。

結(jié)構(gòu)型(Structural)模式:通過類繼承或者對象組合獲得更靈活的結(jié)構(gòu),從而應(yīng)對需求變化為對象的結(jié)構(gòu)帶來的沖擊。

行為型(Behavioral)模式:通過類繼承或者對象組合來劃分類與對象間的職責(zé),從而應(yīng)對需求變化為多個(gè)交互的對象帶來的沖擊。

2.從范圍(實(shí)現(xiàn)手段)來看分為:

類模式處理類與子類的靜態(tài)關(guān)系。

對象模式處理對象間的動(dòng)態(tài)關(guān)系。

3.從封裝變化角度來看分為:


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

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

靜態(tài)->動(dòng)態(tài)

早綁定->晚綁定

繼承->組合

編譯時(shí)依賴->運(yùn)行時(shí)依賴

緊耦合->松耦合

5.“組件協(xié)作”模式

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

典型模式:

Template Method

Strategy

Observer/Event

A.Template Method模式

動(dòng)機(jī)(Motivation):

在軟件構(gòu)建過程中,對于某一項(xiàng)任務(wù),它常常有穩(wěn)定的整體操作結(jié)構(gòu),但各個(gè)子步驟卻有很多改變的需求,或者由于固有的原因(比如框架與應(yīng)用之間的關(guān)系)而無法和任務(wù)的整體結(jié)構(gòu)同時(shí)實(shí)現(xiàn)。

如何在確定穩(wěn)定操作結(jié)構(gòu)的前提下,來靈活應(yīng)對各個(gè)子步驟的變化或者晚期實(shí)現(xiàn)需求?


模式定義:

定義一個(gè)操作中的算法的骨架(穩(wěn)定),而將一些步驟延遲(變化)到子類中。Template

Method使得子類可以不改變(復(fù)用)一個(gè)算法的結(jié)構(gòu)即可重定義(override重寫)該算法的某些特定步驟。

結(jié)構(gòu)(Structure):


要點(diǎn)總結(jié):

Template Method模式是一種非?;A(chǔ)性的設(shè)計(jì)模式,在面向?qū)ο笙到y(tǒng)中有著大量的應(yīng)用。它用最簡潔的機(jī)制(虛函數(shù)的多態(tài)性)為很多應(yīng)用程序框架提供了靈活的擴(kuò)展點(diǎn),是代碼復(fù)用方面的基本實(shí)現(xiàn)結(jié)構(gòu)。

除了可以靈活應(yīng)對子步驟的變化外,“不要調(diào)用我,讓我來調(diào)用你”的反向控制結(jié)構(gòu)是Template Method的典型應(yīng)用。

在具體實(shí)現(xiàn)方面,被Template Method調(diào)用的虛方法可以具有實(shí)現(xiàn),也可以沒有任何實(shí)現(xiàn)(抽象方法、純虛方法),但一般推薦將它們設(shè)置為protected方法。

B.Strategy策略模式

動(dòng)機(jī)(Motivation):

在軟件構(gòu)建過程中,某些對象使用的算法可能多種多樣,經(jīng)常改變,如果將這些算法都編碼到對象中,將會(huì)使對象變得異常復(fù)雜;而且有時(shí)候支持不使用的算法也是一個(gè)性能負(fù)擔(dān)。

如何在運(yùn)行時(shí)根據(jù)需要透明地改變對象的算法?將算法與對象本身解耦,從而避免上述問題?

模式定義:

定義一系列算法,把它們一個(gè)個(gè)封裝起來,并且使它們可互相替換(變化)。該模式使得算法可獨(dú)立于使用它的客戶程序(穩(wěn)定)而變化(擴(kuò)展,子類化)。

結(jié)構(gòu)(Structure)


要點(diǎn)總結(jié):

Strategy及其子類為組件提供了一系列可重用的算法,從而可以使得類型在運(yùn)行時(shí)方便地根據(jù)需要在各個(gè)算法之間切換。

Strategy模式提供了用條件判斷語句以外的另一種選擇,消除條件判斷語句,就是在解耦合。含有許多條件判斷語句的代碼通常都需要Strategy模式。

如果Strategy對象沒有實(shí)例變量,那么各個(gè)上下文可以共享同一個(gè)Strategy對象,從而節(jié)省對象開銷。

C.Observer觀察者模式

動(dòng)機(jī)(Motivation):

在軟件構(gòu)建過程中,我們需要為某些對象建立一種“通知依賴關(guān)系”--一個(gè)對象(目標(biāo)對象)的狀態(tài)發(fā)送改變,所有的依賴對象(觀察者對象)都將得到通知。如果這樣的依賴關(guān)系過于緊密,將使軟件不能很好地抵御變化。

使用面向?qū)ο蠹夹g(shù),可以將這種依賴關(guān)系弱化,并形成一種穩(wěn)定的依賴關(guān)系。從而實(shí)現(xiàn)軟件體系結(jié)構(gòu)的松耦合。

模式定義:

定義對象間的一種一對多(變化)的依賴關(guān)系,以便當(dāng)一個(gè)對象(Subject)的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都得到通知并自動(dòng)更新。

結(jié)構(gòu)(Structure):


要點(diǎn)總結(jié):

使用面向?qū)ο蟮某橄螅琌bserver模式使得我們可以獨(dú)立地改變目標(biāo)與觀察者,從而使二者之間的依賴關(guān)系達(dá)到松耦合。

目標(biāo)發(fā)送通知時(shí),無需指定觀察者,通知(可以攜帶通知信息作為參數(shù))會(huì)自動(dòng)傳播。

觀察者自己決定是否需要訂閱通知,目標(biāo)對象對此一無所知。

Observer模式是基于事件的UI框架中非常常用的設(shè)計(jì)模式,也是MVC模式的一個(gè)重要組成部分。

6.“單一職責(zé)”模式

在軟件組件的設(shè)計(jì)中,如果責(zé)任劃分的不清晰,使用繼承得到的結(jié)果往往是隨著需求的變化,子類急劇膨脹,同時(shí)充斥著重復(fù)代碼,這時(shí)候的關(guān)鍵是劃清責(zé)任。

典型模式:

Decorator

Bridge

D.Decorator裝飾模式

動(dòng)機(jī)(Motivation)

在某些情況下我們可能會(huì)“過度地使用繼承來擴(kuò)展對象的功能”,由于繼承為類型引入的靜態(tài)特質(zhì),使得這種擴(kuò)展方式缺乏靈活性;并且隨著子類的增多(擴(kuò)展功能的增多),各種子類的組合(擴(kuò)展功能的組合)會(huì)導(dǎo)致更多子類的膨脹。

如何使“對象功能的擴(kuò)展”能夠根據(jù)需要來動(dòng)態(tài)地實(shí)現(xiàn)?同時(shí)避免“擴(kuò)展功能的增多”帶來的子類膨脹的問題?從而使得任何“功能擴(kuò)展變化”所導(dǎo)致的影響為最低?

模式定義:

動(dòng)態(tài)(組合)地給一個(gè)對象增加一些額外的職責(zé)。就增加功能而言,decorator模式比生成子類(繼承)更為靈活(消除重復(fù)代碼&減少子類個(gè)數(shù))。

結(jié)構(gòu)(Structure):


要點(diǎn)總結(jié):

通過采用組合而非繼承的手法,Decorator模式實(shí)現(xiàn)了在運(yùn)行時(shí)動(dòng)態(tài)擴(kuò)展對象功能的能力,而且可以根據(jù)需要擴(kuò)展多個(gè)功能。避免了使用繼承帶來的“靈活性差”和“多子類衍生問題”。

Decorator類在接口上表現(xiàn)為is-a

Component的繼承關(guān)系,即Decorator類繼承了Component類所具有的接口。但實(shí)現(xiàn)上又表現(xiàn)為has-a Component的組合關(guān)系,即Decorator類又使用了另外一個(gè)Component類。

Decorator模式的目的并非解決“多子類衍生的多繼承”問題,Decorator模式應(yīng)用的要點(diǎn)在于解決“主體類在多個(gè)方向上的擴(kuò)展功能”——是為“裝飾”的含義。

E.Bridge橋模式

動(dòng)機(jī)(Motivation):

由于某些類型的固有的實(shí)現(xiàn)邏輯,使得它們具有兩個(gè)變化的維度,乃至多個(gè)緯度的變化。

如何應(yīng)對這種“多維度的變化”?如何利用面向?qū)ο蠹夹g(shù)來使得類型可以輕松地沿著兩個(gè)乃至多個(gè)方向的變化,而不引入額外的復(fù)雜度?

模式定義:

將抽象部分(業(yè)務(wù)功能)與實(shí)現(xiàn)部分(平臺實(shí)現(xiàn))分離,使它們都可以獨(dú)立地變化。

結(jié)構(gòu)(Structure):


要點(diǎn)總結(jié):

Bridge模式使用“對象間的組合關(guān)系”解耦了抽象和實(shí)現(xiàn)之間固有的綁定關(guān)系,使得抽象和實(shí)現(xiàn)可以沿著各自的緯度來變化。所謂抽象和實(shí)現(xiàn)沿著各自緯度的變化,即“子類化”它們。

Bridge模式有時(shí)候類似于多繼承方案,但是多繼承方案往往違背單一職責(zé)原則(即一個(gè)類只有一個(gè)變化的原因),復(fù)用性比較差。Bridge模式是比多繼承方案更好的解決方法。

Bridge模式的應(yīng)用一般在“兩個(gè)非常強(qiáng)的變化緯度”,有時(shí)一個(gè)類也有多于兩個(gè)的變化維度,這時(shí)可以使用Bridge的擴(kuò)展模式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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