---
tags: 設計模式
---
# 設計模式簡介
## 軟體設計
#### [定義](https://www.developerdotstar.com/mag/articles/reeves_design.html)
> The final goal of any engineering activity is the some type of documentation. When a design effort is complete, the design documentation is turned over to the manufacturing team. This is a completely different group with completely different skills from the design team. If the design documents truly represent a complete design, the manufacturing team can proceed to build the product. In fact, they can proceed to build lots of the product, all without any further intervention of the designers. After reviewing the software development life cycle as I understood it, I concluded that the only software documentation that actually seems to satisfy the criteria of an engineering design is the source code listings.
- 約三十年前以工廠為導向的思考方式會認為軟體設計的產出物是 UML 圖
- 老闆覺得只要將 UML 圖給工程師 , 就可以讓工程師照圖施工 , 複製出產品.
- 現在的思維則是認為軟體設計的產出是程式碼 (Source Code)
- 但程式並不是可以正常運作就行了, 因為程式碼是給人看的 (機器碼才是機器看的)
所以必須注重軟體設計的品質
- 可讀性
- 可維護性
- 可擴充性
- ...
- 想要寫出好的程式是容易的嗎 !? 是否有能夠參考的東西幫助我們寫出好的程式碼呢 !?
- 物件導向設計模式強調的是以類別、物件、繼承、組合等技巧來完成需求. 意即需要針對需求分析 , 再將軟體功能拆分成不同的類別/模組/元件. 之後再將這些類別進行組裝 , 以完成需求. 但**如何拆分以及如何組裝 , 這極其考驗程式設計師的系統分析以及實作能力...**

## 設計模式發展歷史
> 建築師克里斯托佛·亞歷山大(Christopher Alexander)在1977/79年編制了一本匯集設計模式的書,但是這種設計模式的思想在建築設計領域裡的影響遠沒有後來在軟體開發領域裡傳播的廣泛。
> 肯特·貝克和沃德·坎寧安在1987年,利用克里斯托佛·亞歷山大在建築設計領域裡的思想開發了設計模式,並把此思想應用在Smalltalk中的圖形使用者介面(GUI)的生成中。一年後,埃里希·伽瑪在他的蘇黎世大學博士畢業論文中開始嘗試把這種思想覆寫為適用於軟體開發。與此同時James Coplien 在1989年至1991年也在利用相同的思想致力於 C++ 的開發,而後於1991年發表了他的著作Advanced C++ Programming Styles and Idioms。同年,Erich Gamma 得到了博士學位,然後去了美國,在那與Richard Helm、Ralph Johnson、John Vlissides 合作出版了《設計模式:可復用物件導向軟體的基礎》(Design Patterns - Elements of Reusable Object-Oriented Software) 一書,在此書中共收錄了 23 種設計模式。
> 這四位作者( Erich Gamma 、 Richard Helm、Ralph Johnson、John Vlissides )在軟體開發領域裡以「四人幫」(英語,Gang of Four,簡稱GoF)而聞名,並且他們在此書中的協同運作導致了軟體設計模式的突破。有時,GoF也會用於代指《設計模式》這本書。
> Alexander 對模式 (pattern) 下了如是的定義:「**每個模式**都描述了一個在我們環境中會不斷出現的問題,並進而描述了這個問題解決方案的要素,透過這種方式,解決方案能夠百萬次地反覆應用,但是具體方式又不會完全相同」
> 在軟體工程中,設計模式(design pattern)是對軟體設計中普遍存在(反覆出現)的各種問題,所提出的解決方案
> 設計模式是描述在各種不同情況下,要怎麼解決問題的一種方案。
> 物件導向設計模式通常以類別或物件來描述其中的關係和相互作用,但不涉及用來完成應用程式的特定類別或物件。設計模式能使不穩定依賴相對穩定、具體依賴於相對抽象,避免會引起麻煩的緊耦合,以增強軟體設計面對並適應變化的能力。
- 設計模式一詞起源於建築業. 後人將其概念應用在軟體設計上. 而後四人幫的著作 Gang of Four (GoF) , 更是導致設計模式在軟體設計行業的推廣.
- 當前人(E.G. 四人幫作者) 遇到一個問題 , 他們可以留下解決這個問題的核心實作. 當後人碰到類似的問題時 , 可以依照此核心實作去變化 , 以解決自己的問題. 而這一個**核心實作就是一個設計模式**.
- 導入設計模式的概念能讓軟體開發如同建築設計一樣 , 可以參考前人的設計去加以應對 , 以解決自己所碰到的類似問題. 所以設計模式 , 除了可以節省程式設計師大量的系統分析以及設計的時間 , 也可以提升軟體品質以及可維護性.
## 設計模式
### 設計模式定義
> Each pattern is a three-part rule, wihch **express a relation between a certain context,a problem,and a solution**
> A pattern is a process and a thing
> A pattern is a **proven solution** to a **Recurring problem** in a specific context, and more...
##### 每一種設計模式都是在說明一個已被證實可行的解決方法, 並且描述其解決的問題(可能重複出現)和情境.
### 設計模式的六大元素
我們通常會用這六個元素來描述某一個設計模式
- Name:模式名詞(有名詞命名或動詞命名兩種命名邏輯)
- 名詞命名 --> 描述模式所建立或產生的結果 --- 使用模式後的狀態來為模式命名
- 動詞命名 --> 描述如何達到解決方案所要求的狀態
- Context:描述問題發生的情境
- Problem:描述問題本身
- Force:會影響問題的的限制或是特性
- 沒有限制那就沒有問題(因為隨便都能解), 因此如果沒有 Force 描述問題為什麼很難. 那我們也就無從得知一個 Solution 為什麼好.
- Solution:解決問題的方法 (可能不只一種, 其也可能會有不只一種的 Resulting Context)
- Resulting Context(Consequence):套用 Solution 後的結果
- Consequence 是中性(中立的)的,只是一個現象, 需依照 Context 才能判斷是好是壞.
##### PS : 通常使用 Problem 和 Force 來判斷是否為相同的 Pattern , 而非用程式碼
#### 範例 : 買熱咖啡
- Name :
- 買好燙的咖啡模式
- Context :
- 我習慣早上去家裡附近的全家買咖啡, 但全家僅提供紙杯而非馬克杯
- Problem :
- 全家的熱咖啡超級燙, 需要等其冷卻才拿得起來.
- Force
- 我早上不喝咖啡會提不起勁工作 <--- 一定要喝
- 想要喝熱的咖啡 <--- 不喜歡喝冷的
- 有時候起得晚, 沒有時間慢慢等它冷卻再拿走. <--- 趕上班
- Solution
- 不喝 (被 Force 排除)
- 自己帶冰塊去加, 加速冷卻 (被 Force 排除)
- 等它冷卻後再拿走 (被 Force 排除)
- 使用全家提供的杯套
- Resulting Context(Consequence)
- 不用等咖啡冷卻後, 就可以將其帶走或品嘗
- 多拿一個杯套, 之後要丟的垃圾增加 <--- 可以接受的結果
### 找設計模式的兩種策略
- Solution -> Problem & Forces -> Context
- 先觀察現行 Solution 來反推出 Force, 然後再來考慮是否修改 Solution
- Specification By Example ( Key Example )
- TDD 精神
- 先列舉所有重要的 Context (Test Case)
- 再看看是否需要修改 Solution, 若需要則修改
##### PS : 實務上會兩種策略同時搖擺進行, 看哪個先找到答案.
##### PS : 套設計模式時, 也請一次套一個模式, 套完後再觀察 Consequence 是否符合期望. 若不符合, 再繼續套XD
### 設計模式好處
- 別人的設計就是好的設計 (站在巨人的肩膀上) , 不需要自己再花時間去思考如何做出好的設計
- 每一種設計模式都遵守物件導向設計原則
- 設計模式是我們遵守物件導向設計原則後為了達成某個特定的軟體需求 , 所完成的實作方式.
- 每一種設計模式都能夠解決一再重複出現的問題
- 某些問題同質性非常高 , 它經常會出現在不同的軟體實做中. 而設計模式就是針對這些一再出現的問題所歸納出的解決方法.
- 每一種設計模式都是解決某一個問題的核心實作
- 設計模式通常會針對問題的核心點分析 , 並且經過一般化的思考以及歸納 , 為了讓其可以適應更多的變化以解決更多類似的問題.
- 每一種設計模式都可以重複使用
- 設計模式可以重複被使用在解決類似的問題上. 最終成為數以萬計類似問題的解決方式.
- 舉例來說 : 遊戲攻略就是一種設計模式 , 五人組隊要過某一個副本 , 我們可以依照攻略去決定五人腳色的分配或是在各種情況下應該採取的動作. 如果我們都按照攻略進行 , 那麼就可以順利過關.
## 設計模式的分類(依照用途)
- Creational patterns (生成模式)
- 定義
> These patterns provide various object creation mechanisms, which increase flexibility and reuse of existing code.
- Problem : How do you Create objects ?
- 抽象化產生物件的過程
- 將產生物件與管理物件的職責獨立
- 這些模式提供不同產生物件的方式.
- Factory Method
- Abstract Factory
- Builder
- Prototype
- Singleton
- Structural patterns (結構模式)
- 定義
> These patterns explain how to assemble objects and classes into larger structures while keeping these structures flexible and efficient.
- Problem : How do you Compose classes and objects to form larger structures ?
- 透過組合不同的類別或是物件來產生更大的結構 , 以便完成更高/複雜層次的邏輯需求
- 結構模式注重如何將外部介面和內部實作進行組合 (e.g. Adapter) 以及如何組合多個物件以實現新的功能
- 這些模式提供如何組裝物件與類別到一個更大的結構之中的方式.
- Adapter
- Bridge
- Composite
- Decorator
- Façade
- Flyweigh
- Proxy
- Behavioral patterns (行為模式)
- 定義
>These patterns are concerned with algorithms and the assignment of responsibilities between objects.
- Problem : How do you Assign algorithms and responsibilities between objects ?
- 行為模式考慮類別或物件之間的演算法與責任分配的問題
- 行為模式描述多個物件或類別間如何溝通或偕同運作
- 這些模式提供類別與物件間互動或是責任分配的方式.
- Interpreter
- Template Method
- Command
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Chain of Responsibility
- Visitor
-
##### PS : GOF 書中一共有 23 種設計模式.
## 結論
- 設計模式是前人的智慧也是學習物件導向程式設計的最佳範本 , 我們可以從此學習到在實作某個需求時 , 如何將功能切分成不同的類別 , 並且再將它們組裝起來 , 以完成需求.
- 設計模式可以減少程式設計師思考的時間(不用從頭思考) , 因為設計模式是某些問題的解決方案 , 所以我們可以參考其實作方式並加以變化 , 以解決自己的問題.
- GOF 提出的設計模式已經經過時間的驗證 (20 多年...?). 許多都已成為程式設計的準則 , 甚至內化到程式語言之中了 E.g. Iterator
- **如果說 SOLID 設計原則是我們設計程式時應該遵守的原則或是心法 , 那設計模式就是 SOP 模板 , 只要按照步驟執行 , 就可以輕易地達成 SOLID 原則對於程式的要求.**
- **設計模式只是一種解決問題的方法 , 這代表我們在解決自己的問題時 , 並不需要完全按照設計模式的結構 , 可以適時地加入自己的變化.**
- 設計模式只是提出一個規範和定義 , 並不代表那是唯一的解決方法. 因此當我們針對某個設計模式進行修改/變形 , 只要其符合 GOF 所表達的情境 , 就可以說是實作 XXX 模式了.
## 參考資源
[Design Patterns這樣學就會了:入門班 Day1 教材](https://www.slideshare.net/teddysoft/design-pattern-day1201307published)
[What Is Software Design?](https://www.developerdotstar.com/mag/articles/reeves_design.html)
[設計模式 (電腦)](https://zh.wikipedia.org/wiki/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F_(%E8%AE%A1%E7%AE%97%E6%9C%BA))
[DAY5: 簡單介紹設計模式](https://ithelp.ithome.com.tw/articles/10234315?sc=hot)
[The Catalog of Design Patterns](https://refactoring.guru/design-patterns/catalog)
[什麼是Pattern(1):第一個例子](http://teddy-chen-tw.blogspot.com/2015/05/pattern-1pattern.html)
[什麼是Pattern(2):修正Problem](http://teddy-chen-tw.blogspot.com/2015/05/pattern-2pattern.html)
[什麼是Pattern(3):修正Solution](http://teddy-chen-tw.blogspot.com/2015/05/pattern-3pattern.html)
[什麼是Pattern(4):修正Context](http://teddy-chen-tw.blogspot.com/2015/05/pattern-4context.html)
[什麼是Pattern(5):加入Force](http://teddy-chen-tw.blogspot.com/2015/05/pattern5force.html)
[來一個解決問題的公式 – Design Patterns 這樣學就會了心得](https://blog.yveslin.com/2015/06/08/design-patterns-%E9%80%99%E6%A8%A3%E5%AD%B8%E5%B0%B1%E6%9C%83%E4%BA%86%E5%BF%83%E5%BE%97/)
---
###### Thank you!
You can find me on
- [GitHub](https://github.com/s0920832252)
- [Facebook](https://www.facebook.com/fourtune.chen)
若有謬誤 , 煩請告知 , 新手發帖請多包涵
# :100: :muscle: :tada: :sheep:
<iframe src="https://skilltree.my/c67b0d8a-9b69-47ce-a50d-c3fc60090493/promotion?w=250" width="250" style="border:none"></iframe>