前言
接上篇 設計模式,Let's “Go”! (上), 繼續更新設計模式,今天介紹的設計模式有模板模式、迭代器模式、組合模式、狀態模式、代理模式、橋接模式和建造者模式;
文章對設計模式的特點和使用場景進行了總結,每個設計模式分配的篇幅較少,給了解過設計模式的作為速查,幫不了解設計模式的入門, 當然具體實現才是重點,使用現實生活中的事物例子來幫助理解設計模式。
放上 Go 實現設計模式的源碼地址:DesignPattern-枕邊書-Github ,偶有更新,歡迎 star
。
文章經常被人爬,而且還不注明原地址,我在這里的更新和糾錯沒法同步,這里注明一下原文地址:http://www.cnblogs.com/zhenbianshu/p/7449868.html 以防誤人子弟。
模板模式(Template)
介紹
模板模式:模板模式在抽象類或父類
中抽象出算法步驟
作為模板,模板的具體細節推遲到子類實現。
- 模板模式在父類或抽象類中定義一個
算法的骨架
,並在父類或抽象類中實現共同的部分,各個不同的步驟由不同的子類分別實現; - 模板板式在父類的算法步驟中定義
勾子(hook)
,在子類中判斷並定義一些不是非通用步驟; - 模板模式與策略模式的不同之處在於,策略模式是針對多個不同的算法,而模板模式是針對一個算法的不同步驟,在模板模式中,只有一個算法;
場景
- 多個算法有多個共同之處,但某些步驟略微不同;
- 各子類步驟順序一致,但步驟的具體實現有所不同時;
實現
- 有發郵件和發短信兩種通訊方式;
- 他們都需要獲取目標信息、格式化正文、填寫發送方信息,但實現不同;
- 在信息類中抽象出三個步驟,具體的處理方式由兩種通訊方式各自實現;
- 發送信息時調用信息類中的發送方法,發送方法會按照順序自動調用對應的步驟;
迭代器模式(Iterator)
介紹
迭代器模式:迭代器模式允許調用者在不知道類內部實現
的情況下遍歷類元素
。
- 迭代器接口常用方法有
length(),next(),previous(),remove()
等; - 各類在內部實現迭代器接口,用對應的方法操作元素;
- 調用者不考慮類內部實現,調用迭代器接口即可;
場景
- 類使用不同的數據結構存儲數據;
- 需要對不同的數據類型進行遍歷等操作;
實現
- 使用 slice 存儲一列戰馬,使用 map 存儲一列士兵;
- 戰馬和士兵結構都實現了迭代器接口;
- 獲取戰馬數和士兵數,遍歷戰馬和士兵,調用迭代器接口即可;
組合模式(Composite)
介紹
組合器模式:使用一種組件抽象
來同時表達集合與元素
,使用統一的接口來管理集合和元素。
- 組合模式通常為
樹結構
,父結點和子節點具有同樣的抽象和接口; - 在操作集合時,會
同時操作集合所屬的具體元素
; - 通常給組合模式添加一個迭代器來完成組合結構的迭代;
場景
- 管理的多個對象構成樹型層級結構;
- 操作高層級的對象時,需要同時其所屬的下級對象,如界面窗口等;
實現
- 將軍、隊長、士兵構成樹型層級結構,且他們都是戰士,擁有戰斗方法;
- 每位戰士都保存着自己的下級名單,沒有下級時忽略;
- 每個人在戰斗時,都會率領着下級戰斗;
狀態模式(State)
介紹
狀態模式:狀態模式抽象出一個事物的狀態
作為類,解耦事物和不同狀態下的行為;
- 狀態模式通過替換狀態對象作為狀態轉換的方式;
- 狀態對象實現根據狀態動作的接口,可以根據不同的
動作做出對應
的反應; - 狀態模式與策略模式的實現相似,但狀態模式是對類內部狀態作出改變,而策略模式是針對算法封裝;
場景
- 事物有多種狀態,且可以相互轉換;
- 事物多種狀態下對同一動作做出的行為不同;
實現
- 植物有 幼苗、開花和成熟 三種狀態,且它們會通過澆水和收獲的動作進行相互轉換;
- 幼苗和開花時不能收獲,只能澆水,成熟狀態只能收獲,不需要再澆水;
- 定義三種狀態,和它們對不同動作時的行為,植物通過三種對象的替換來進行狀態轉換;
代理模式(Proxy)
介紹
代理模式:給對象提供一個代理,由代理對象控制對原對象的調用;
- 代理模式為一個對象(通常是大對象或無法復制的對象)
創建另外一個類作為其訪問的接口
,所有對真實對象的請求都通過代理對象
完成; - 代理對象可以
控制用戶對真實對象的訪問權限
,也可以在訪問真實對象時附加功能; - 代理模式可被用作:遠程代理,虛擬代理,安全代理,指針引用,延遲加載;
場景
- 對象無法被直接訪問時;
- 對象過大,初始化較慢;
- 對象不必要立刻初始化,可使用默認值代替;
實現
- 小明給暗戀對象寫了一封信,在等回信;
- 郵遞員是個非常忙的人,來不及去收取回信;
- 小明好聲好氣向郵遞員要回信時,郵遞員都推拖說自己要去取;
- 小明發怒了,郵遞員終於抽時間去取了信給小明;
- 此信中郵遞員就是代理模式中的代理,他實現了懶加載。
- 回信內容見源碼:)
橋接模式(Bridge)
介紹
橋接模式:將事務的多個維度
都抽象出來以解耦抽象與實際
之間的綁定關系,使抽象和實際向着不同維度改變;
- 橋接模式通過對象的組合來解決事物的多維度變化問題,以替代多繼承的不靈活;
- 橋接模式可以輕易在多維度上拓展,而不改變原有模式;
- 橋接模式與策略模式的不同之處:策略模式是針對一個不變的主題替換抽象算法,而橋接模式是策略模式的高維度狀態,它的主題也可能會被替換;
場景
- 某事物在多個維度上都有變化;
- 無法使用多繼承或使用多繼承會很不靈活;
實現
- 作畫時可以使用鉛筆和圓珠筆等不同的筆,也可以在宣紙或普通A4紙;
- 抽象出筆和紙兩種對象;
- 自由組合筆和紙進行作畫;
建造者模式(Builder)
介紹
建造者模式:建造者模式分離創建復雜對象的過程和細節
,使得同樣的創建過程能創建不同的對象。
- 建造者模式將創建對象部件的
一般過程抽象出接口
,而由不同的建造者類實現具體的接口,實現過程的步驟; - 通過建造者,調用者不用考慮對象創建過程的細節,且建造者也可以被靈活替換;
- 與模板模式的區別:建造者模式使用類的組合進行對象的創建,而模板模式使用類的繼承實現對象的具體構造;
- 與工廠模式的區別:工廠模式會返回一個具體類,而建造者模式會建造出一個由多個類組裝而成的完整類;
場景
- 對象的創建包含其他對象為類元素,創建過程復雜;
- 多個復雜對象的創建過程具有高度相似性;
實現
- 中國式建築有金色屋頂和紅色大門,而意式建築有圓項和白色大門;
- 中國建築師和意式建築師分別擅長建造不同類型的建築;
- 我們在蓋不同類型的房子時先創建一個建築師,再用建築師去創建對應風格的房子;
小結
開發者對設計模式常陷入兩個誤區,要么極度推崇,要么棄如弊履。 極度推崇的人認為設計模式就是聖經,是程序設計的最高實現,以至於寫代碼時就往設計模式上湊,最終寫出的代碼冗余沉重,讓人很難懂;而鄙棄設計模式的人實用至上,認為寫出的代碼能實現業務功能就好,對設計模式理也不理,結果代碼雜亂不堪,稍有改動就引出一大堆 BUG,跟別人解釋實現時,別人聽得雲里霧里。
我認為設計模式就是一些定義,就像冒泡排序、快速排序這些名字一樣,便於開發者之間的交流,特別是在代碼中,如果你提到使用了XX模式,如果閱讀你代碼的人也了解這個設計模式,那么他了解你的實現也就更加簡單了。像之前在不了解設計模式的概念時,我就已經在很多地方應用模板模式和策略模式了,但在向別人介紹代碼實現時,我需要說一堆代碼設計,別人還不一定能理解,如果以后再跟人交流時,我不需要解釋很多,只說我實現了模板模式就OK了。而且學會並深入了解了設計模式,那么以后遇到適用設計模式的場景,就可以不用苦逼地一遍遍修改代碼,而直接朝着最美的方向設計了。
所以深入學習設計模式也是學習程序設計中很多問題的普遍解決方式,也是學習程序員之前交流的專業詞匯,意義還是挺重大的。
關於本文有什么問題可以在下面留言交流,如果您覺得本文對您有幫助,可以點擊下面的 推薦 支持一下我。博客一直在更新,歡迎 關注 。