天天看點

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

設計模式

設計模式是面向對象的最佳實踐(代碼無錯未必優)

(适度封裝,合理繼承,結構多态)=》降耦合;

整體已維護,易複用,可擴充=》靈活度;

面向對象的好處:可維護,可擴充,可複用,靈活性好;

面向對象的标志:依賴倒轉=》抽象不應該依賴細節,細節應該依賴于抽象=》程式中所有的依賴關系都終止于抽象類或者接口(對象之間的中間者);

面向對象程式設計原則:開放封閉原則,依賴倒置原則;

1.簡單工廠模式 factory(解決對象建立問題)--電腦,加功能

[工廠模式是定義一個擁有建立對象的接口,讓子類決定執行個體化哪一個類]

a、電腦,計算對象工廠

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 2.政策者模式 strategy(政策:算法,解決算法建立,使算法變化不影響算法的客戶)--商場促銷

[政策模式是定義一系列算法的方法,所有算法完成相同的工作,以相同的方式調用所有的算法,減少各種算法類和使用算法之間的耦合,分離算法類簡化單元測試。政策模式封裝了變化規則-處理變化的可能性,及不同時間應用不同規則。]

a、收銀軟體(工廠+政策)

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 3.抽象工廠模式 abstract factory -- -- DB更換

工廠方法模式是定義一個用于建立對象的接口,讓子類決定執行個體化哪一個類。

(提供一個建立一系列相關或互相依賴對應的接口,而無需指定他們具體的類)

a、資料庫實作更換

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 抽象工廠模式(Abstract Factory),提供一個建立一系列相關或互相依賴對象的接口,而無需指定他們具體的類。工廠和産品都是抽象構成,抽象之間互相依賴,具體實作交給使用端控制。

抽象工廠模式的優缺點:

優點:a.易于交換産品系列,具體工廠類隻需要初始化時出現一次,使得更改工廠非常容易。

b.讓具體的建立執行個體過程與用戶端分離,用戶端通過抽象接口操縱執行個體

缺點:a.增加抽象實作時對應需要修改的地方比較多,多次調用時遇變動需要修改的地方遞增

優化方案:反射+抽象工廠+配置檔案(開放-封閉原則:對擴充開放,對修改關閉)

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 從這個方面上來說:所有的用簡單工廠的地方,都可以用反射技術去除switch或if,解除耦合

4.單一職責原則 Single responsibility Principle --拍攝ufo

解釋:就一個類而言,應該隻有一個引起它變化的原因。

例子:俄羅斯方塊的遊戲邏輯(數組操作)和界面渲染屬于不同的職責應該分開編寫。

在應用單一職責設計軟體時,應該發現職責并把那些職責互相分離。如果能想到多于一個的動機去改變一個類,那麼這個類就具有多于一個的職責。

程式設計時,要在類的職責分離上多思考,做到單一職責,這樣代碼才能真正的易維護、易擴充、易複用、靈活多樣。

5.開放-封閉原則 The Open-Closed Principle --考研工作兩不誤

解釋:軟體實體(類、子產品、函數等)應該可以擴充,但是不可修改。

面對需求,對程式的改動是通過增加新代碼進行的,而不是更改現有的代碼。

開放-封閉原則是面向對象設計的核心所在。遵循這個原則可以帶來面向對象技術所聲稱的巨大好處,也就是可維護、可擴充、可複用、靈活性好。開發人員應該僅對程式中呈現出頻繁變化的那部分做出抽象,然而,對于應用程式的每個部分都刻意的進行抽象同樣不是一個好主意。拒絕不成熟的抽象和抽象本省一樣重要。

6.依賴倒轉原則 --修電腦與修收音機

A.高層子產品不應該依賴低層子產品。兩個都應該依賴抽象。

B.抽象不應該依賴細節。細節應該依賴抽象。

7.裡氏代換原則 --企鵝不能代換會飛的鳥類(不能複用)

子類型必須能夠替換它們的父類型。正是由于子類型的可替換性才使得父類型的子產品在無需修改的情況下就可以擴充。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 依賴倒轉其實可以說是面向對象設計的标志,用哪種語言來編寫程式不重要,如果編寫時考慮的都是如何針對抽象程式設計而不是針對細節程式設計,即程式中所有的依賴關系都是終止于抽象類或者接口,那就是面向對象設計,反之那就是過程化的設計了。

8.裝飾模式(Decorator)--穿什麼

動态的給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成子類更為靈活。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 裝飾模式能有效的把類的核心職責和裝飾功能區分開,而且可以去除相關類中重複的裝飾邏輯。

9.代理模式(Proxy)--為别人做嫁衣,班長

為其他對象提供一種代理以控制對這個對象的通路。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 代理模式應用:

a.遠端代理,也就是為一個對象在不同的位址空間提供局部代表。這樣可以隐藏一個對象存在于不同位址空間的事實。

b.虛拟代理,是根據需要建立開銷很大的對象。通過他來存放執行個體化需要很長時間的真實對象。(html圖檔下載下傳)

c.安全代理,用來控制真實對象通路時的權限。(用于對象有不同通路權限時)

d.智能指引,是指當調用真實的對象時,代理處理另外一些事。

10.工廠方法模式(Factory Method)--學雷鋒,社群志願者類

定義一個用于建立對象的接口讓子類決定執行個體化哪一個類.工廠方法是一個類的執行個體化延遲到其子類。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 簡單工廠 VS 工廠方法

簡單工廠模式:的最大優點在于工廠類中包含了必要的邏輯判斷,根據用戶端的選擇條件動态執行個體化相關的類,對于用戶端來說,去除了與具體産品的依賴。

工廠方法模式:實作時,用戶端需要決定執行個體化哪一個工廠來實作運算類,選擇判斷的問題還是存在的,也就是說,工廠方法把簡單的工廠的内部邏輯判斷移到了用戶端代碼來進行。想要加功能,本來是修改工廠類的,而現在是修改用戶端。

工廠方法客服了簡單工廠違背開放封閉原則的缺點,有保持了封裝對象建立過程的優點。集中封裝了對象的建立,使得要更換對象時,不需要做大的改動就可以實作,降低了客戶程式與産品對象的耦合。工廠方法模式是簡單工廠模式的進一步抽象和推廣。

11.原型模式(Prototype) --手寫履歷,影印履歷

用原型執行個體指定建立對象的種類,并且通過拷貝這些原型建立新的對象。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 原型模式其實就是從一個對象再建立另外一個可定制的對象,不需知道任何建立細節

它不用重新初始化對象,而是動态的獲得對象運作時的狀态

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 java中實作方法

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 淺複制vs深複制:

淺複制:被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。clone

深複制:把引用對象的變量指向複制過的新對象,而不是原有的被引用的對象。copy

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 12.模闆方法模式 -- 考題抄錯會做也白搭

定義一個操作的算法的骨架,而将一些步驟延遲到子類中。模闆方法使得子類可以不改變一個算法的結構即可重定義概算法的某些特定步驟。

當我們要完成在某細節層次一緻的一個過程或一系列步驟,但其個别步驟在更詳細的層次上的實作可能不同時,我們通常考慮用模闆方法模式來處理。使父類成為子類的模闆,所有重複的代碼要上升到父類去,而不是讓每個子類都去重複。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 當不變的和可變的行為在方法子類實作中混合在一起時,不變行為就會在子類中重複出現,通過模闆方法模式把這些行為搬移到單一的地方,這樣就幫助子類擺脫重複的不變行為的糾纏。

13.迪米特法則(最小知識原則) --無熟人難辦事

如果兩個類不必彼此直接通信,那麼這兩個類就不應當發生直接的互相作用。如果其中一個類需要調用另一個類的某一個方法的話,可以通過第三者轉發這個調用。

強調在類的結構設計上,每個類都應當盡量降低成員的通路權限。

迪米特法則其根本思想,是強調類之間的松耦合。類之間的耦合越弱,越有利于複用,一個處于弱耦合的類被修改,不會對關系的類造成波及。

14.外觀模式(門面模式) --股票與基金經理人

外觀模式(Facade):為子系統的一組接口提供一個一緻的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 外觀模式的使用時機:

1.在設計初期階段,應該要有意識的将不同的兩個層分離,在層與層之間建立外觀Facade

2.在開發階段,子系統往往因為不斷的重構演化而變得越來越複雜,增加外觀Facade可以可提供一個簡單的接口,減少它們之間的依賴

3.在維護一個遺留的大型系統時,可能這個系統已經非常難以維護和擴充,但是新需求開發又必須依賴于它,可以為新系統開發一個外觀Facade類,來提供設計粗糙或高度複雜的遺留代碼的比較清晰簡單的接口,讓新系統與Facade對象互動,Facade與遺留代碼互動所有複雜的工作。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 15.建造者模式 --中餐味道不穩定,西餐味道穩定

将一個複雜對象的建構和它的表示分離,使得同樣的建構過程可以建立不同的表示。

使用時機:在建立複雜對象時和建構過程分離。

16.觀察者模式 --老闆回來,我不知道

觀察者模式又叫做釋出-訂閱(Publish/Subscribe)模式

觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀态發生變化時,會通知所有的觀察者對象,使它們能都自動更新自己。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 觀察者模式特點:

将系統分割成一系列分割成一系列互相協作的類有一個很不好的副作用,那就是需要維護相關對象間的一緻性。我們不希望為了維持一緻性而使各個類緊密耦合,這樣會給維護、擴充和重用都帶來不便。當一個對象的改變需要同時改變其他對象的時候适合使用觀察者模式。

觀察者模式所做的工作其實就是解除耦合。讓耦合的雙方都依賴于抽象,而不是依賴于具體。進而使得各自變化都不會影響另一邊的變化。

觀察者模式的不足:通知者和觀察者之間互相不知道,需要由用戶端來決定通知誰。

彌補觀察者模式的不足--事件委托機制:

委托就是一個引用方法的類型。一旦為委托配置設定了方法,委托将與該方法具有完全相同的行為。委托方法的使用可以像其他任何方法一樣,具有參數和傳回值。委托可以看作是對函數的抽象,是函數‘類’,委托的執行個體将代表一個具體的函數。一個委托可以搭載多個方法,所有方法被依次喚起。它可以使得委托對象對搭載的方法并不需要屬于同一個類。

委托的前提是委托對象所搭載的所有方法必須具有相同的原形和形式,也就是擁有相同的參數清單和傳回值類型。

17.狀态模式

面向對象設計其實就是希望做到代碼的責任分解。

狀态模式(state):當一個對象的内在狀态改變時允許改變其行為,這個對象看起來像是改變了其類。

狀态模式主要解決的是當控制一個對象狀态轉換的條件表達式過于複雜的情況。把狀态的判斷邏輯轉移到表示不同狀态的一系列類當中,可以把複雜的判斷邏輯簡化。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 好處:将與特定狀态相關的行為局部化,并且将不同狀态的行為分割開來。

将特定的狀态相關的行為都放入一個對象中,由于所有與狀态相關的代碼都存在于某個ConcreteState中,是以通過定義新的子類可以很容易的增加新的狀态和轉換。消除龐大的條件分支語句,大的分支判斷會使得它們難以修改和擴充。狀态模式通過把各種狀态邏輯分布到state的子類之間,來減少互相的依賴。

用處:當一個對象的行為取決于它的狀态,并且它必須在運作時刻根據狀态改變它的行為時,就可以考慮使用狀态模式。

工作狀态-狀态模式:

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 18.擴充卡模式 --電源擴充卡,姚明需要翻譯

擴充卡模式(Adapter),将一個類的接口轉換成客戶希望的另一個接口。Adapter模式使得原本由于接口不能相容而不能一起工作的那些類可以一起工作。

軟體開發中,系統的資料和行為都正确,但接口不符時,我們應該考慮用擴充卡,目的是使控制範圍之外的一個原有對象與某個接口比對。擴充卡模式主要應用于希望複用一些現存的類,但是接口又與複用環境要求不一緻的情況。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 球員擴充卡:

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 19.備忘錄模式

備忘錄(Memento):在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。這樣以後就可将該對象恢複到原先儲存的狀态。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 将要儲存的細節封裝到Memento中,哪一天要更改儲存的細節也不用影響用戶端。

Menento模式比較使用于功能比較複雜的,但需要維護或記錄屬性曆史的類,或者需要儲存的屬性隻是衆多屬性中的一小部分中,Originator可以根據儲存的Menento資訊還原到前一狀态。使用備忘錄可以把複雜的對象内部資訊對其他的對象屏蔽起來,恰當的封裝邊界。

遊戲備忘錄:

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 20.疊代器模式 -- 上車買票

疊代器模式(Iterator),提供一種方法順序通路一個聚合對象中各個元素,而又不暴露該對象的内部表示。

需要通路全部聚焦對象,需要聚焦有多種方式周遊,為不同的聚集結構提供如開始、下一個、是否結束、目前哪一項等統一的接口。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 疊代器模式就是分離了集合對象的周遊行為,抽象出一個疊代器來負責,這樣既可以做到不暴露集合的内部結構,又可以讓外部代碼透明地通路集合内部的資料。

21.單例模式 -- 有些類也需要計劃生育

單例模式Singleton:保證一個類僅有一個執行個體,并提供一個通路它的全家通路點。

通常我們可以讓一個全局變量使得一個對象被通路,但它不能防止你執行個體化多個對象。一個最好的辦法就是,讓類自身負責儲存它的唯一執行個體。這個類可以保證沒有其他執行個體可以被建立,并且它可以提供一個 通路該執行個體的方法。

所有類都有構造方法,不編碼則系統預設生成空的構造方法,若有顯示定義的構造方法,預設的構造方法就會失效。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 好處:單例模式因為Singleton類封裝它的唯一執行個體,這樣它可以嚴格地控制客戶怎樣通路它以及何時通路它,簡單地說就是對唯一執行個體的受控通路。

多線程時的單例:(并發通路時可能會造成建立多個執行個體)

可以給程序一把鎖來處理,lock確定當一個線程位于代碼的臨界區時,另一個線程進入臨界區。如果其他線程視圖進入鎖定的代碼,則它将一直等待(即被阻止),直到該對象被釋放。

懶漢初始化:

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 雙重鎖定:double-check-locking

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 餓漢模式:靜态初始化-類加載時初始化

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 22.合成/聚合複用原則(CARP)-- 松耦合

合并/聚合複用原則:盡量使用合成/聚合,盡量不要使用類繼承。

合成(Composition)和聚合(Aggrega)都是關聯的特殊種類。聚合表示一種弱的”擁有“關系,展現的是A對象可以包含B對象,但是B對象不是A對象的一部分;合成則是一種強的”擁有“關系,展現了嚴格的部分和整體的關系,部分和整體的生命周期一樣。例如大雁和翅膀的關系是合成,大雁和雁群的關系是聚合。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 合成/聚合複用原則的好處是,優先使用對象合成/聚合将有助于你保持每個類被封裝,并被集中在的單個任務上。這樣類和類繼承層次會保持較小規模,并且不太可能增長為不可控制的龐然大物。

對象的繼承關系時在編譯時就定義好了,是以無法在運作時改變從父類繼承的實作。子類的實作與它的父類有非常緊密的依賴關系,以至于父類實作中的任何變化必然會導緻子類發生變化。當你需要複用子類時,如果繼承下來的實作不适合解決新問題,則父類必須重寫或被其他更合适的類替換。這種依賴關系限制了靈活性并最終限制了複用性。

優先使用對象的合成或聚合,而不是類繼承。合成/聚合更加松耦合。

22.橋接模式 -- 手機軟體何時統一

橋接模式(Bridge),将抽象部分與它的實作部分分離,使它們都可以獨立地變化。

抽象與它地實作分離,并不是說,讓抽象類與其派生類分離,因為這沒有任何意義。實作指的是抽象類和它地派生類用來實作自己地對象。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 實作系統可能有多角度分類,每一種分類都有可能變化,那麼就把這種多角度分離出來讓它們獨立變化,減少他們之間的耦合。

隻要正真深入了解了設計原則,很多設計模式其實就是原則的應用而已,或許在不知不覺中就在使用設計模式了!

23.指令模式 -- 烤羊肉串的緊耦合

行為請求者與行為實作者的緊耦合存在很多隐患

指令模式(Command),将一個請求封裝為一個對象,進而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支援可撤銷操作。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 例如烤肉店運用指令模式

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 指令模式作用:

第一:它能較容易地設計一個指令隊列;

第二:在需要地情況下,可以較容易地将指令記入日志;

第三:允許接收請求地一方決定是否要否決請求;

第四:可以容易地實作對請求地撤銷和重做;

第五:由于加進新的具體指令類不影響其他的類,是以增加新的具體指令類很容易;

指令模式把請求一個操作的對象與知道怎麼執行一個操作的對象分割開

靈活開發原則告訴我們,不要為代碼添加基于猜測的、實際不需要的功能。如果不清楚一個系統是否需要指令模式,一般就不要着急去實作它,事實上,在需要的時候通過重構實作這個模式并不困難,隻有在真正需要如撤銷/恢複操作等功能時,把原來的代碼重構為指令模式才有意義。

24.責任鍊模式 -- 加新非要老總批?

如果涉及的的處理流程太多,全部寫在一個分支裡面,一個類責任太多。違背了單一職責原則與開放封閉原則。

責任鍊模式(Chain of Responsibility):使多個對象都有機會處理請求,進而避免請求得發送者和接受者之間得耦合關系。将這些對象連成一條鍊,并沿着這條鍊傳遞該請求,直到有一個對象處理它為止。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 責任鍊的好處:當客戶送出一個請求時,請求是沿鍊傳遞直至有一個ConcreteHandler對象負責處理它。

接受者和發送者都沒有對方的明确資訊,且鍊中的對象自己也并不知道鍊的結構。結果是職責鍊可簡化對象的互相連接配接,它們僅需保持一個指向其後繼者的引用,而不需保持它們所有的候選接受者的引用,這就極大降低了耦合度。也可以随時增加或修改處理一個請求的結構。增強了給對象指派職責的靈活性。需要注意是一個請求可能到了鍊末端都得不到處理,或者因為沒有正确配置而得不到處理。

25.中介者模式 -- 世界需要和平,聯合國

将一個系統分割成許多對象通常可以增加其可複用性,但是對象間互相連接配接的激增又會降低其可複用性。大量連接配接使得一個對象不可能在沒有其他對象的支援下工作,系統表現為一個不可分割的整體,是以,對系統的行為進行任何較大的改動就十分困難了。

中介者模式(Mediator)用一個中介對象來封裝一系列的對象互動。中介者使各個對象不需要顯式地互相引用,進而使其耦合松散,而且可以獨立地改變它們之間地互動。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 中介者模式優缺點:

中介者模式很容易在系統中應用,也很容易在系統中誤用。當系統出現‘多對多’互動複雜地對象群時,不要急于使用中介者模式,而要先反思你地系統在設計上是不是合理。

Mediator的出現減少了各個Colleague的耦合,使得可以獨立地改變和複用各個Colleague類和Mediator。由于把對象如何協作進行了抽象,将中介作為一個獨立地概念并将其封裝在一個對象中,這樣關注地對象就從對象各自本身的行為轉移到它們之間的互動上來,也就是站在一個更宏觀的角度去看待系統。

中介者可能會因為互動對象越來越多變得非常複雜,由于ConcreteMediator控制了集中化,于是就把互動複雜性變成了中介的複雜性,這就使得中介者會變得比任何一個ConcreteColleague都複雜。

典型中介者模式:電腦程式,所有控件得互動都是由Form窗體來作中介,操作各個對象。

中介者模式一般應用于一組對象以定義良好但是複雜的方式進行通信的場合,以及想定制一個分布在多個類中的行為,而又不想生成太多的子類的場合。

26.享元模式 -- 項目多也别傻做

享元模式(Flyweight)運用共享技術有效的地支援大量細粒度的對象。

【設計模式】設計模式(一)-- 大話設計模式讀書筆記

 在享元對象内部并不會随環境的改變而改變的共享部分,可以稱為享元對象的内部狀态,而随環境改變而改變的、不可以共享的狀态就是外部狀态。

享元模式可以避免大量非常相似類的開銷。在程式設計中,有時需要生成大量細粒度的類執行個體來表示資料。如果能發現這些執行個體除了幾個參數外基本都是相同的,有時就能夠受大幅度地減少需要執行個體化的類的數量。如果能把那些參數移到類執行個體的外面,在方法調用時将它們傳遞進來,就可以通過共享大幅度地減少單個執行個體地數目。

享元模式應用:

如果一個應用程式使用了大量地對象,而大量的這些對象造成了很大的存儲開銷時就應該考慮使用;還有就是對象的大多數狀态可以是外部狀态,如果删除對象的外部狀态,那麼可以用相對較少的共享對象取代很多組對象,此時可以考慮使用享元模式。