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的設計模式的學習貼,最後謝謝大家的支援。