大話設計模式:第29章 模式總結

第29章:模式總結

  • 鬆耦合

內聚性描述的是一個例程內部組成部分之間相互聯繫的緊密程度。

耦合性描述的是一個例程與其他例程之間聯繫的緊密程度。

軟件開發中,創建的例程應該是:內部完整,也就是高內聚;與其他例程之間的聯繫則小巧、直接、可見、靈活,這就是鬆耦合。

  • 面向對象

在做面向對象的開發,創建對象的工作不可避免。創建對象時,負責創建的實體通常需要了解要創建的是哪個具體的對象,以及何時創建這個而非那個對象的規則。而我們如果希望遵循開放-封閉原則依賴倒轉原則里氏代換原則,那使用對象時,就不應該知道所用的是哪一個特選的對象。此時就需要“對象管理者”工廠來負責此事。在對象創建時,都可以通過工廠的手段來避免指明具體對象,減少耦合性。另外,在創建對象時,使用抽象工廠、原型、建造者的設計比使用工廠方法要更靈活,但它們也更加複雜。通常,設計是以使用工廠方法開始,當設計者發現需要更大的靈活性時,設計便會向其他創建型模式演化。

總之,在面向對象開發過程中,爲了避免耦合,都多多少少會應用工廠方法來幫助管理創建對象的工作。工廠方法的實現並不能減少工作量,但是它能夠在必須處理新情況時,避免使已經很複雜的代碼更加複雜。

面向對象設計模式最本質的體現是抽象的思想,類是對對象的抽象,抽象類是對類的抽象,接口是對行爲的抽象。

在這裏插入圖片描述

簡單工廠模式在擴展時要更改工廠類,即對修改開放,不符合開放封閉原則,慎用。

創建型模式

抽象工廠、建造者、工廠方法、原型、單例

創建型模式隱藏了類的實例是如何被創建和放在一起,整個系統關於這些對象所知道的是由抽象類所定義的接口。這樣,創建型模式在創建了什麼、誰創建它、它是怎麼被創建的,以及何時創建這些方面提供了很大的靈活性。當一個系統應該獨立於它的產品創建、構成和表示時,應該考慮用創建性模式。

創建型模式抽象了實例化的過程。它們幫助一個系統獨立於如何創建、組合和表示它的那些對象。創建型模式都會將關於該系統使用哪些具體的類的信息封裝起來。允許客戶用結構和功能差別很大的“產品”對象配置一個系統。配置可以是靜態的,即在編譯時指定,也可以是動態的,即在運行時再指定。

通常設計應該是從是工廠方法開始,當設計者發現需要更大的靈活性時,設計便會向其他創建型模式演化。當設計者在設計標準之間進行權衡的時候,瞭解多個創建型模式可以給設計者更多的選擇餘地。

new的角度講,工廠方法是最好的設計,它是把工廠職責都分了類,其它幾種模式是它的變體。

  1. 抽象工廠:提供一個創建一系列或相關依賴對象的接口,而無需指定它們具體的類。

在這裏插入圖片描述

  1. 建造者:將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。

建造者將一個複雜對象的構建與它的表示分離,用同樣的構建過程創建不同的產品給客戶。

在這裏插入圖片描述

  1. 工廠方法:定義一個用於創建對象的接口,讓子類決定實例化哪一個類,工廠模式使一個類的實例化延遲到其子類。

在這裏插入圖片描述

  1. 原型:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。

建立相應數目的原型並克隆它們通常比每次用合適的狀態手工實例化該類更方便一些。

在這裏插入圖片描述

  1. 單例:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

對一些類來說,單一實例是很重要的。單例模式讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例可以被創建,並且還提供了一個訪問該實例的方法。這就使得對唯一的實例可以嚴格地控制客戶怎樣以及何時訪問它。

在這裏插入圖片描述

結構型模式

適配器、橋接、組合、裝飾、外觀、享元、代理

信息的隱藏促進了軟件的複用,類之間的耦合越弱,越有利於複用,一個處在弱耦合的類被修改,不會對有關係的類造成波及。如果兩個類不必彼此直接通信,那麼就不要讓這兩個類發生直接的相互作用。如果實在需要調用,可以通過第三者來轉發調用。

  1. 適配器:將一個類的接口轉換成客戶希望的另外一個接口。適配器模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。

面向對象的精神是更好地應對需求的變化,而現實中往往會面臨想使用一個已經存在的類,而它的接口不符合要求,或者希望創建一個可以複用的類,該類可以與其他不相關的類或不可預見的類協同工作。適配器滿足開放封閉原則,讓接口不同的類通過適配後,協同工作。

在這裏插入圖片描述

  1. 橋接:將抽象部分與它的實現部分分離,使它們都可以獨立地變化。

繼承是好的東西,但往往會過度地使用,繼承會導致類的結構過於複雜,關係太多,難以維護,而更糟糕的是擴展性非常差。如果能發現繼承體系中,有兩個甚至多個方向的變化,那麼就解耦這些不同方向的變化,通過對象組合的方式,把兩個角色之間的繼承關係改爲了組合的關係,從而使這兩者可以應對各自獨立的變化。橋接滿足合成聚合複用原則,面對變化,主張找出變化並封裝。

在這裏插入圖片描述

  1. 組合:將對象組合成樹形結構以表示“部分-整體”的層次結構,組合模式使得用戶對單個對象和組合對象的使用具有一致性。

組合模式使用戶忽略組合對象與單個對象的不同,用戶將可以統一地使用組合結構中的所有對象。用戶使用組合類接口與組合結構中的對象進行交互,如果接收者是一個葉節點,則直接處理請求;如果接收者是組合對象,通常將請求發送給它的子部件,並在轉發請求之前或之後執行一些輔助操作。組合模式的效果是客戶可以一致地使用組合結構和單個對象。任何用到基本對象的地方都可以使用組合對象。

在這裏插入圖片描述

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

面對變化,如果採用生成子類的方法進行擴充,爲支持每一種擴展的組合,會產生大量的子類,使得子類數目呈爆炸性增長。如果這些子類只是爲某個對象增加一些職責, 此時通過裝飾的方式,可以更加靈活、以動態、透明的方式給單個對象添加職責,並在不需要時,撤銷相應的職責。

在這裏插入圖片描述

  1. 外觀:爲子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

應該讓一個軟件中的子系統間的通信和相互依賴關係達到最小,具體辦法是引入一個外觀對象,它爲子系統間提供了一個單一而簡單的屏障。通常企業軟件的三層或NN層架構,層與層之間地分離其實就是外觀模式的體現。

在這裏插入圖片描述

  1. 享元:爲運用共享技術有效地支持大量細粒度的對象。

對象使得內存佔用過多,而且如果都是大量重複的對象,那就是資源的極大浪費,會使得機器性能減慢。面向對象技術有時會因簡單化的設計而代價極大。可以讓所有相同的對象都共享同一個對象,這可以節約大量的內存。

在這裏插入圖片描述

  1. 代理:爲其他對象提供一種代理以控制對這個對象的訪問。

代理與外觀的主要區別在於,代理對象代表一個單一對象而外觀對象代表一個子系統;代理的客戶對象無法直接訪問目標對象,由代理提供對單獨的目標對象的訪問控制,而外觀的客戶對象可以直接訪問子系統中的各個對象,但通常由外觀對象提供對子系統各元件功能的簡化的共同層次的調用接口。

代理與適配器,都屬於一種銜接性質的功能。代理是一種原來對象的代表,其他需要與這個對象打交道的操作都是和這個代表交涉。而適配器則不需要虛構出一個代表者,只需要爲應付特定使用目的,將原來的類進行一些組合。

在這裏插入圖片描述

行爲型模式

觀察者、模板方法、命令、狀態、職責鏈、解釋器、中介者、訪問者、策略、備忘錄

對象間,尤其是具體對象間,相互知道的越少越好(解除對象間的緊耦合關係),這樣發生改變時才不至於互相影響。

代碼重複是編程中最常見、最糟糕的“壞味道”,如果在一個以上的地方看到相同的程序結構,那麼可以肯定,設法將它們合而爲一,程序會變得更好。完全相同的代碼存在明顯的重複,而微妙的重複會出現在表面不同但是本質相同的結構或處理步驟中,必需小心處理。

優先使用對象組合,而非類繼承。

  1. 觀察者:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。

目標和觀察者不是緊密耦合的,它們可以屬於一個系統中的不同抽象層次,目標所知道的僅僅是它有一系列的觀察者,每個觀察者實現Observer的簡單接口,觀察者屬於哪一個具體類,目標是不知道的。

在這裏插入圖片描述

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

繼承的一大好處是能免費地從基類獲取一些東西,當繼承一個類時,派生類馬上就可以獲得基類中所有的功能,還可以在它的基礎上任意增加新的功能。模板方法模式由一個抽象類組成,這個抽象類定義了需要覆蓋的可能有不同實現的模板方法,每個從這個抽象類派生的具體類將爲此模板實現新方法。這使得所有可重複的代碼都提煉到抽象類中了,實現了代碼重用。

在這裏插入圖片描述

  1. 命令:將一個請求封裝爲一個對象,從而使你可用不同的請求對客戶進行參數化:可以對請求排隊或記錄請求日誌,以及支持可撤銷的操作。

將請求發送者與具體實現者分離,就是將調用操作的對象與知道如何實現該操作的對象解耦,因此可以在不同的時刻指定、排列和執行請求;或者在實施操作前將狀態存儲起來,以便支持取消、重做的操作;還可以記錄整個操作的日誌,以便在系統出問題時查找原因或恢復重做;可以支持事務,要麼所有的命令全部執行成功,要麼恢復到什麼也沒執行的狀態。

在這裏插入圖片描述

  1. 狀態:允許一個對象在其內部狀態改變時改變它的行爲,讓對象看起來似乎修改了它的類。

如果條件分支語句沒有涉及重要的商務邏輯或者不會隨着時間的變化而變化,也不會有任何的可擴展性,換句話說,它幾乎不會變化,此時條件分支是應該使用的。但事實並非如此,狀態模式提供了一個組織與特定狀態相關的代碼的方法,決定狀態轉移的邏輯不在單塊的ifswitch中,而是分佈在各個狀態子類之間,由於所有與狀態相關的代碼都存在於某個狀態子類中,所以通過定義新的子類可以很容易地增加新的狀態和轉換。

在這裏插入圖片描述

  1. 職責鏈:使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。

當有多個對象可以處理一個請求, 哪個對象處理該請求事先並不知道,要在運行時刻自動確定,此時,最好的辦法就是讓請求發送者與具體處理者分離,讓客戶在不明確指定接收者的情況下,提交一個請求,然後由所有能處理這請求的對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。

在這裏插入圖片描述

  1. 解釋器:給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。

如果一種特定類型的問題發生的頻率足夠高,那麼可以考慮將該問題的各個實例表述爲一個簡單語言中的句子。即,構建一個解釋器,用該解釋器解釋這些句子來解決該問題。比如正則表達式就是描述字符串模式的一種標準語言,與其爲每一個字符串模式都構造一個特定的算法,不如使用一種通用的搜索算法來解釋執行一個正則表達式,該正則表達式定義了待匹配字符器的集合。

在這裏插入圖片描述

  1. 中介者:用一箇中介對象來封裝一系列的對象交互。 中介者使各對像不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。

面向對象設計鼓勵將行爲分佈到各個對象中,這種分佈可能會導致對象間有許多連接。也就是說,有可能每一個對象都需要知道其他許多對象。對象間的大量相互連接使得一個對象似乎不太可能在沒有其他對象的支持下工作,這對於應對變化是不利的,任何較大的改動都很困難。將集體行爲封裝一個單獨的中介者對象來避免這個問題,中介者負責控制和協調一組對象間的交互。中介者充當一箇中介以使組中的對象不再相互顯式引用。這些對象僅知道中介者,從而減少了相互連接的數目。即中介者主要考慮最少知識原則,也就是如何減少耦合的問題,類之間的耦合越弱,越有利於複用。

在這裏插入圖片描述

  1. 訪問者:一個作用於某對象結構中的各元素的操作,可以在不改變各元素的類的前提下定義作用於這些元素的新操作。

訪問者增加具體的Element是困難的,但增加依賴於複雜對象結構的構件的操作就變得容易。僅需增加一個新的訪問者即可在一一個對象結構上定義一個新的操作。

在這裏插入圖片描述

  1. 策略:定義一系列的算法,把它們一一封裝起來,並且使它們可相互替換。本模式使得算法可獨立於使用它的客戶而變化。

繼承提供了一種支持多種算法或行爲的方法,可以直接生成一個類A的子類BCD,從而給它以不同的行爲。但這樣會將行爲硬行編制到父類A當中,而將算法的實現與類A的實現混合起來,從而使得類A難以理解、難以維護和難以擴展,而且還不能動態地改變算法。仔細分析會發現,它們之間的唯一差別是它們所使用的算法或行爲,將算法封裝在獨立的策略Strategy類中使得你可以獨立於其類A改變它,使它易於切換、易於理解、易於擴展。 策略模式使用對象組合要優於類繼承。

在這裏插入圖片描述

  1. 備忘錄:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到原先保存的狀態。

備忘錄模式可以避免暴露一些只應由對象A管理卻又必須存儲在對象A之外的信息。備忘錄模式把可能很複雜的對象A的內部信息對其他對象屏蔽起來,從而保持了封裝邊界。

在這裏插入圖片描述

  1. 迭代器:提供一種順序訪問一個聚合對象中各個元素的方法,而又不需要暴露該對象的內部表示。

迭代器並不知道一個集合對象中具體是些什麼對象元素,但迭代器提供一種方法來讓別人可以訪問它的元素,而且可能要以不同的方式遍歷這個集合。迭代器模式的關鍵思想是將對列表的訪問和遍歷從列表對象中分離出來並放入一個迭代器對象中,迭代器類定義了一個訪問該列表元素的接口。迭代器對象負責跟蹤當前的元素,並且知道哪些元素已經遍歷過了。

在這裏插入圖片描述

P.S.:MVCModelViewController)模式:包括三類對象,Model是應用對象,View是它在屏幕上的表示,Controller定義用戶界面對用戶輸入的響應方式。如果不使用MVC,則用戶界面設計往往將這些對象混在一起,而MVC則將它們分離以提高靈活性和複用性。MVC是多種模式的綜合應用,集觀察者、組合、策略三者優點於一身,是一種架構模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章