Go語言從面世就受到了業界的普遍關注,隨着區塊鏈的火熱Go語言的地位也急速躥升,為了讓讀者對設計模式在Go語言中有一個初步的了解和概念,本偏對Go語言中的設計模式進行了整合和歸納,希望能對大家的學習起到一定的幫助。
設計模式背景和起源
在介紹設計模式的起源之前,我們先要了解一下模式的誕生與發展。與很多軟件工程技術一樣,模式起源於建築領域,畢竟與只有幾十年歷史的軟件工程相比,已經擁有幾千年沉淀的建築工程有太多值得學習和借鑒的地方。
每個模式都描述了一個在我們的環境中不斷出現的問題,然后描述了該問題的解決方案的核心,通過這種方式,我們可以無數次地重用那些已有的成功的解決方案,無須再重復相同的工作。這個定義可以簡單地用一句話表示:
模式是在特定環境下人們解決某類重復出現問題的一套成功或有效的解決方案。
設計模式是什么
俗話說:站在別人的肩膀上,我們會看得更遠。設計模式的出現可以讓我們站在前人的肩膀上,通過一些成熟的設計方案來指導新項目的開發和設計,以便於我們開發出具有更好的靈活性和可擴展性,也更易於復用的軟件系統。
設計模式的一般定義如下:
設計模式(Design Pattern)是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結,使用設計模式是為了可重用代碼、讓代碼更容易被他人理解並且保證代碼可靠性。
狹義的設計模式是指GoF在《設計模式:可復用面向對象軟件的基礎》一書中所介紹的23種經典設計模式,不過設計模式並不僅僅只有這23種,隨着軟件開發技術的發展,越來越多的新模式不斷誕生並得以應用。
設計模式一般包含模式名稱、問題、目的、解決方案、效果等組成要素,其中關鍵要素是模式名稱、問題、解決方案和效果。
模式名稱(Pattern Name)通過一兩個詞來描述模式的問題、解決方案和效果,以便更好地理解模式並方便開發人員之間的交流,絕大多數模式都是根據其功能或模式結構來命名的;
問題(Problem)描述了應該在何時使用模式,它包含了設計中存在的問題以及問題存在的原因;
解決方案(Solution)描述了一個設計模式的組成成分,以及這些組成成分之間的相互關系,各自的職責和協作方式,通常解決方案通過UML類圖和核心代碼來進行描述;
效果(Consequences)描述了模式的優缺點以及在使用模式時應權衡的問題。
Go語言模式分類
在分類之前,我們需要明白模式的大體分類,以及他們都分別代表什么意思:
創建模式:對類的實例化過程的抽象。一些系統在創建對象時,需要動態地決定怎樣創建對象,創建哪些對象,以及如何組合和表示這些對象。創建模式描述了怎樣構造和封裝這些動態的決定。包含類的創建模式和對象的創建模式。
結構模式:描述如何將類或對象結合在一起形成更大的結構。分為類的結構模式和對象的結構模式。類的結構模式使用繼承把類,接口等組合在一起,以形成更大的結構。類的結構模式是靜態的。對象的結構模式描述怎樣把各種不同類型的對象組合在一起,以實現新的功能的方法。對象的結構模式是動態的。
行為模式:對在不同的對象之間划分責任和算法的抽象化。不僅僅是關於類和對象的,並是關於他們之間的相互作用。類的行為模式使用繼承關系在幾個類之間分配行為。對象的行為模式則使用對象的聚合來分配行為。
模式分類表:
所屬類型 | 模式名稱 | 模式 | 簡單定義 |
---|---|---|---|
創建模式 | Abstract Factory | 抽象工廠 | 提供用於創建相關對象系列的接口 |
Builder | 生成器 | 使用簡單對象構建復雜對象 | |
Factory Method | 工廠方法 | 將對象的實例化延遲到用於創建實例的專用函數 | |
row 2 col 2 | 對象池 | 實例化並維護一組相同類型的對象實例 | |
Singleton | 單例 | 將類型的實例化限制為一個對象 | |
結構模式 | Adapter | 適配器 | 適配另一個不兼容的接口來一起工作 |
Bridge | 橋接 | 將接口與其實現分離,以便兩者可以獨立變化 | |
Composite | 組合 | 封裝並提供對許多不同對象的訪問 | |
Decorator | 裝飾 | 靜態或動態地向對象添加行為 | |
Facade | 外觀 | 使用一種類型作為許多其他類型的API | |
Flyweight | 享元 | 運用共享技術有效地支持大量細粒度的對象 | |
Proxy | 代理 | 為對象提供代理以控制其操作 | |
行為模式 | Chain of Responsibility | 職責鏈 | 避免通過提供超過對象處理請求的機會來將發送方與接收方耦合 |
Command | 命令 | 捆綁命令和參數以便稍后調用 | |
Mediator | 中介者 | 連接對象並充當代理 | |
Memento | 備忘錄 | 生成可用於返回先前狀態的不透明令牌 | |
Observer | 觀察者 | 提供回調以通知事件/數據更改 | |
Registry | 注冊 | 跟蹤給定類的所有子類 | |
State | 狀態 | 根據內部狀態封裝同一對象的不同行為 | |
Strategy | 策略 | 允許在運行時選擇算法的行為 | |
Template | 模板 | 定義一個將某些方法推遲到子類的框架類 | |
Visitor | 訪問者 | 將算法與其運行的對象分開 | |
同步模式 | Condition Variable | 條件變量 | 為線程提供一種機制,以暫時放棄訪問以等待某些條件 |
Lock/Mutex | 鎖定/互斥 | 對資源實施互斥限制以獲得獨占訪問權限 | |
Monitor | 監視器 | 互斥和條件變量模式的組合 | |
Read-Write Lock | 讀寫鎖定 | 允許並行讀取訪問,但僅對資源的寫入操作進行獨占訪問 | |
Semaphore | 信號 | 允許控制對公共資源的訪問 | |
並行模式 | N-Barrier | N-二道閘 | 阻止進程繼續進行,直到所有N個進程都到達屏障 |
Bounded Parallelism | 有界並行 | 完成大量資源限制的獨立任務 | |
Broadcast | 廣播 | 把一個消息同時傳輸到所有接收端 | |
Coroutines | 協同程序 | 允許在特定地方暫停和繼續執行的子程序 | |
Generators | 生成器 | 一次性生成一系列值 | |
Reactor | 反應 | 服務處理程序使用I/O多路復用策略來同步、有序的處理一個或多個客戶端並發請求 | |
Parallelism | 並行 | 完成大量獨立任務 | |
Producer Consumer | 生產者消費者 | 從任務執行中分離任務 | |
Scheduler | 調度器 | 協調任務步驟 | |
消息傳遞模式 | Fan-In | 扇入 | 該模塊直接調用上級模塊的個數,像漏斗型一樣去工作 |
Fan-Out | 扇出 | 該模塊直接調用的下級模塊的個數 | |
Futures & Promises | Futures & Promises | 扮演一個占位角色,對未知的結果用於同步 | |
Publish/Subscribe | Publish/Subscribe | 將信息傳遞給訂閱者 | |
Push & Pull | Push & Pull | 把一個管道上的消息分發給多人 | |
穩定模式 | Bulkheads | Bulkheads | 實施故障遏制原則(即防止級聯故障) |
Circuit-Breaker | 斷路器 | 當請求有可能失敗時,停止流動的請求 | |
Deadline | 截止日期 | 一旦響應變緩,允許客戶端停止一個正在等待的響應 | |
Fail-Fast機制 | 快速失敗 | 檢查請求開始時所需資源的可用性,如果不滿足要求則失敗 | |
Handshaking | 握手 | 詢問組件是否可以承受更多負載,如果不能,則請求被拒絕 | |
Steady-State | 穩定狀態 | 為每一個服務積累一個資源,其它服務必須回收這些資源 | |
剖析模式 | Timing Functions | 時序功能 | 包裝函數並記錄執行 |
成例 | Functional Options | 功能選項 | 允許給默認值創建clean API和慣用重載 |
反模式 | 級聯故障 | 級聯故障 | 互連部件系統中的故障,其中部件的故障導致多米諾骨牌效應 |
個人觀點
作為設計模式的忠實粉絲和推廣人員,在正式學習設計模式之前,我結合多年的工作經驗和學習心得,這里給出了下列個人的建議:
-
掌握設計模式並不是件很難的事情,關鍵在於多思考,多實踐,不要聽到人家說懂幾個設計模式就很“牛”,只要用心學習,設計模式也就那么回事,你也可以很“牛”的,一定要有信心。
-
在學習每一個設計模式時至少應該掌握如下幾點:這個設計模式的意圖是什么,它要解決一個什么問題,什么時候可以使用它;它是如何解決的,掌握它的結構圖,記住它的關鍵代碼;能夠想到至少兩個它的應用實例,一個生活中的,一個軟件中的;這個模式的優缺點是什么,在使用時要注意什么。當你能夠回答上述所有問題時,恭喜你,你了解一個設計模式了,至於掌握它,用多了自然就掌握了。
-
“如果想體驗一下運用模式的感覺,那么最好的方法就是運用它們”。正如很多書里所說的,無論學習什么都要做到知行合一。
-
千萬不要濫用模式,不要試圖在一個系統中用上所有的模式。每個模式都有自己的適用場景,不能為了使用模式而使用模式,濫用模式不如不用模式,因為濫用的結果得不到“藝術品”一樣的軟件,很有可能是一堆垃圾代碼。
-
如果將設計模式比喻成“三十六計”,那么每一個模式都是一種計策,它為解決某一類問題而誕生,不管這個設計模式的難度如何,使用頻率高不高,我建議大家都應該好好學學,多學一個模式也就意味着你多了“一計”,說不定什么時候一不小心就用上了,
-
設計模式的“上乘”境界:“手中無模式,心中有模式”。模式使用的最高境界是你已經不知道具體某個設計模式的定義和結構了,但你會靈活自如地選擇一種設計方案【其實就是某個設計模式】來解決某個問題,設計模式已經成為你開發技能的一部分,能夠手到擒來,“內功”與“招式”已渾然一體,要達到這個境界並不是看完某本書或者開發一兩個項目就能夠實現的,它需要不斷沉淀與積累,所以,對模式的學習不要急於求成。
隨着筆者的不斷學習和深入,在后面也會帶領大家逐個去深入學習設計模式的意義和使用,喜歡的小伙伴可以點點關注,我會定期更新Go的設計模式的學習貼,最后謝謝大家的支持。