# Design Pattern ## Creational Pattern(創建型模式) >將物件具現化的過程抽象化的加以萃取,使系統能獨立於物件的建立、組成及表現方式之外。 ### Factory Method >[提供一個工廠介面,將產生實體的程式碼交由子類別各自實現](https://skyyen999.gitbooks.io/-study-design-pattern-in-java/content/factory.html)  [圖片來源](https://refactoring.guru/design-patterns/factory-method) **Character** 1. Creator:負責創建特定類型物件(e.g. Product),interface/abstract class。 2. Product:創建物件的的共同特性,interface/abstract class。 3. ConcreteCreator:實體工廠 4. ConcreteProduct:實體產品 以生產麵包為例。 先定義一個麵包種類介面,並且 implement 出不同的麵包種類(吐司 & 蛋糕)實體。 再定義一個抽象麵包工廠類別負責生產麵包,接著建立出不同種類麵包的工廠實體,override createProduct() 這個方法,所以能夠將不同種類麵包的製作方法分離出去,然後回傳該麵包的實體。 如果想要增加不同種類麵包的製作原料,必須增加各種原料實體(Concrete Product)與原料工廠(Concrete Creator),將會生成大量的子類別使關係變得相當複雜。 因此可使用抽象工廠(Abstract Factory)的設計模式來解決。 **Advantage** 1. 隱藏創立物件的細節(同簡單工廠) 2. 加入新 Product 不需要改動 Creator,直接繼承即可,Client 用法也不需要修改 **Disadvantage** 1. 工廠方法的 factoryMethod,只能創建一個對象(e.g. 麵包) 2. ConcreteCreator 跟 ConcreteProduct 會成對的增加 --- ### Abstract Factory >[用一個工廠介面來產生一系列相關的物件,但實際建立哪些物件由實作工廠的子類別來實現](https://skyyen999.gitbooks.io/-study-design-pattern-in-java/content/abstractFactory1.html) 著重在一整族物件的生成  [圖片來源](https://refactoring.guru/design-patterns/abstract-factory) **Character** 1. Creator:負責創建特定類型物件(e.g. Product),interface/abstract class 2. Product:創建物件的的共同特性,interface/abstract class * ==可以有兩個以上的抽象 Product== * 這些 Product 之間有抽象關係 4. ConcreteCreator:實體工廠 5. ConcreteProduct:實體產品 同上,以生產麵包為例,這次需要拆分不同的原料進行分工(e.g. 麵粉 & 油)。 定義出各種原料介面,並 implement 出不同的原料實體,接著同樣定義出一個抽象麵包工廠,其中的方法包含生產該產品會使用到的原料,回傳該原料的物件,然後 implement 出不同產品的實體工廠,這些實體工廠會使用各種原料實體來生產產品。 **Advantage** 1. Factory Method & Abstract Factory 都在實踐一個重要觀念,隔離客戶端實際產生的物件(Product),以便日後擴充不受影響(open/close) 2. 高內聚低耦合 3. open/close:僅限增加 Concrete Factory 和 Product **Disadvantage** 1. 若增加 Abstract Product,則Abstract Factory, Concrete Factory 會需要修改 --- ### Builder >把一個複雜物件的建構與樣貌分離,如此相同的建構過程可以產生不同樣貌的物件 重視一步步建構物件的流程,常會與 composite 搭配使用 與 Abstract Factory 很像,差別在於 Builder pattern 把 build 過程封裝起來了,而且此模式更加專注零件裝配的==順序==,一般用來建立更為複雜的物件。 當一個類別擁有多個屬性,==有的屬性是必要,而有的屬性是選擇性的時候==,或看到某類別有很多個建構式,或==建構式有很多參數==,而且在呼叫建構式時常傳一些null進去的情況,就很適合用Builder Pattern來重構。  [圖片來源](https://refactoring.guru/design-patterns/builder) Builder Pattern將物件的建構過程(construction of the object)抽離成為以下的 Builder、ConcreteBuilder 及 Director。 以生產車子為例。 工頭(Director)知道所有種類車子的生產流程,而所有車子的抽象生產流程稱為 Builder,工頭再把每一種流程(Concrete Builder)都定義出來,最後再請工人按照規定的步驟製造出車子(Product)。 **Character** 1. Product:最終要被建構物件的類別 2. Builder:用來定義建構物件過程中各必要步驟(方法)的介面 3. ConcreteBuilder:實作 Builder 介面,實際用來建構物件的類別 4. Director:負責指揮 ConcreteBuilder 該如何建構物件 **Advantage** 1. 產品的建造和表示分離,實現了解耦 2. 將複雜產品的建立步驟分解在不同的方法中,使得建立過程更加清晰 3. 增加新的具體建造者無需修改原有類庫的程式碼,易於拓展,符合 open/close 原則 **Disadvantage** 1. 產品必須有共同點,限制了使用範圍 2. 如內部變化複雜,會有很多的建造類,難以維護 --- ### Prototype >[Prototype屬於為Creational design patterns, 可使用已建立好的Prototype將資訊直接複製到新物件上](https://ithelp.ithome.com.tw/articles/10194600) 首先需要先了解 **Shallow copy** 和 **Deep copy** 的差異 當產生一個新的物件所要花費過大的成本,例如產生過程太複雜、產生過程需要使用者操作的物件個體,抑或是希望把框架和所產生的物件個體分開時,適合使用 Prototype Pattern。 Prototype Pattern 在 Java 圖 ### Singleton >[保證一個類別只會產生一個物件,而且要提供存取該物件的統一方法](https://skyyen999.gitbooks.io/-study-design-pattern-in-java/content/singleton.html)  [圖片來源](https://refactoring.guru/design-patterns/singleton) 在類別中宣告一個靜態成員變數(static field)的實例,並將建構子設為 private ,再搭配公開的靜態方法(public static method),提供外部存取指定的實例,且確保該實例是==全域唯一的實體==。 **Advantage** 1. 簡單方便,提供唯一的入口來操作物件,能夠透過getInstance() 獲得物件 **Disadvantage** 1. 所有 Singleton 物件都會先被建造出來,不管有沒有用到,可以使用延遲初始(lazy initialization)的方式,當第一次使用時才建立實例。 ### 小結 使用「欲生成的物件類別」參數化系統共有兩種方法: 1. 衍生出子類別(e.g. Factory Method) 3. 物件複合策略(e.g. Abstract Factory, Builder, Prototype) * Abstract Factory 可產生出許多類別的成品物件 * Builder 會用一套複雜的協定一步步拼裝打造物件 * Prototype 以複製原型個體的方式打造成品物件 通常會先用 Factory Method 設計系統,等到彈性不夠時,再求助於其他生成模式。 ## Structural Pattern(結構型模式) >探討如何以類別和建組合成大型的結構,常會分為兩種模式: >1. 類別結構模式(Structural Class Patterns):透過繼承機制組合出外部介面和內部實作 >2. 物件結構模式(Structural Object Patterns):著重在組合物件以實現新的功能 ### Adapter >[轉接器模式將一個類別的介面,轉換成別一個介面以供客戶使用。轉接器讓原本介面不相容的類別可以合作無間。(e.g. 轉接頭)](http://corrupt003-design-pattern.blogspot.com/2016/07/adapter-pattern.html) **Object Adapter Pattern 物件配接器**  [圖片來源](https://refactoring.guru/design-patterns/adapter) 使用組合物件的原則(Object Composition Principle),讓主程式與 Adapter 藉由共通的介面來溝通,而 Adapter 負責將傳遞進來的訊息轉換成被包裝物件所需要的格式,並調用合適的介面。 **Class Adapter Pattern 類別配接器**  [圖片來源](https://refactoring.guru/design-patterns/adapter) 此方法透過繼承(Inheritance)來達成類似的效果,但只有部分支援多重繼承(Multiple Inheritance)的程式語言例如 Python 以及 C++ 才能使用。 **Character** 1. Client Interface(Existing Class):定義 Client 所用的與應用領域相關之介面 2. Client:與符合 Client Interface 的物件合作 3. Service:需要被轉換的既有介面 4. Adapter:將 Service 轉換成 Client Interface **Advantage** 1. 符合單一職責原則(Single Responsibility Principle),資料轉換的職責跟商業邏輯的部分是分開的 2. 符合開放封閉原則(Open-Close Principle),Adapter 讓原有的類別去適應了新的主程式,但並沒有改變原有的類別封裝好的行為 **Disadvantage** 1. 對 Client 不夠透明化,Adapter 物件不再遵從 Service 介面 2. 整個軟體的程式碼複雜度會因為加入新的介面和類別而增加 --- ### Bridge >將實作體系與抽象體系分離開來,讓兩者能各自更動各自演進。  [圖片來源](https://refactoring.guru/design-patterns/bridge) **Character** 1. Abstraction:抽象類別,將原本的主體抽換到只剩下虛擬的概念(e.g. 人類,只是吃喝拉撒睡的主體、遙控器,只是開機關機調整的主體) 2. Refined Abstraction:根據不同的需求實作主體 3. Implementor:將原本主體的實際功能抽離,成為這個的Hierarchy(繼承結構),(e.g. 人類,吃喝拉撒睡拉出在此結構實作) 4. ConcretImplementor:根據不同的需求開發真實的行為 **Advantage** 1. 將實作跟介面鬆綁,且可以各自擴充,不會影響到對方,此外可以在==執行期動態設定與抽換== 2. 對於實際的行為改變,不會影響呼叫端 3. 隱藏內部實作細節 **Disadvantage** 1. 如果只有一種 ConcretImplementor 那 Implementor 就沒有存在的必要,但如果是為了類別內的改變不會波及既有的客戶碼,那 Bridge 仍然有幫助 --- ### Composite >將物件組織成樹狀結構、「部分-全體」層級關係,讓外界以一致性的方式對待個別物件和整體物件  [圖片來源](https://refactoring.guru/design-patterns/composite) **Character** 1. Component:宣告複合體內含物建之介面,提出所有類別共有的操作,以及宣告存取子節點、父節點(可有可無)的方法 2. Leaf:代表複合結構之終端物件,定義基本物件的行為,Leaf 不包含子節點 3. Composite:定義含子結構的節點之行為,實作出 Component 操縱複合體的物件 4. Client:透過 Component 介面操縱複合體的物件 **Advantage** 1. 定義包含基本物件和複合物件的類別階層,藉此組合出複雜的物件 2. 簡化客戶碼,Client 不需要知道所面對的是 Leaf or Composite 3. 容易添加新的 Component 類型 **Disadvantage** 1. 難以約束 Component 中 Compoiste 的種類數量 --- ### Decorator >將額外權責動態附加於物件身上,不必衍生子類別即可彈性擴增功能  [圖片來源](https://refactoring.guru/design-patterns/decorator) ConcreteComponent & Decorator 都必須遵守著共同的介面 Component,而 ConcreteDecorator 繼承自 Decorator,因此也要遵守 Component 介面。 Client 先建立出 **Character** 1. Component:制定可被 Decorator 動態添加權責的物件之介面 2. ConcreteComponent:定義可被 Decorator 動態添加權責的物件 3. Decorator:持有指向 Component 的 reference。須制定符合 Component 的介面 4. ConcreteDecorator:將額外權責添加到 Component 身上 **Advantage** 1. 比靜態的繼承機制更有彈性 2. 避免將功能過剩的類別擺在類別階層頂端 **Disadvantage** 1. Decorator 和 Component 不一樣,物件一旦掛上了 Decorator 就和原本的不一樣了 2. 小型物件過多 --- ### Facade >[目的是用一個高層介面包裝各個子系統,由這個統一對外介面與客戶端進行溝通。例如為一個 library、frameworrk 或任何其他複雜的物件組成提供一個簡化的介面。](https://ithelp.ithome.com.tw/articles/10227186)  [圖片來源](https://refactoring.guru/design-patterns/facade) 當一個系統越來越龐大,包含了相當多個子系統時,客戶端就會被迫要了解很多子系統的細節,導致學習曲線增加,也會提高客戶端與子系統內部的相依性,因此可以使用 Facade 整合子系統內部瑣碎的細節,再提供對外互動的單一窗口,讓子系統更加容易使用,隔離客戶端對子系統內部元件的相依性。 **Advantage** 1. 能讓程式與複雜的子系統隔離開來 **Disadvantage** 1. Facade 這個物件可能會變成跟客戶端所有類別都耦合的 God Object(Anti-Pattern,一個了解過多或者負責過多的物件) ## Behavioral Pattern(行為型模式) ### Template Method >[樣板方法模式將一個演算法的骨架定義在一個方法中,而演算法本身會用到的一些方法,則是定義在次類別中。樣板方法讓次類別在不改變演算法架構的情況下,重新定義演算法中的某些步驟。](http://corrupt003-design-pattern.blogspot.com/2016/07/template-method-pattern.html)  Template pattern 的概念是把一個功能拆成多個小步驟,每個小步驟就是一個 method,然後用一個 template method 把這些小步驟組合起來變成一個功能。其中的小步驟可以是沒有具體的內容,也可以是已經有預設行為的。然後把這些小步驟跟 template method 放到一個 base class,然後再去創造 sub class 來繼承 base class 並改寫需要的小步驟。 **Advantage** 1. 將大功能拆成許多小步驟,修改小步驟相對比直接修改大功能來的安全 2. 能夠將重複的程式碼提取到抽象類別中 **Disadvantage** 1. 客戶端容易受到演算法框架的限制 2. 演算法步驟越多越難維護 3. 可能違反里氏替換原則(Liskov Substitution Principle) * [子類別繼承父類別時,除添加新的方法外,盡量不要重寫父類別的方法](http://c.biancheng.net/view/1324.html) --- ### Strategy >[將各種可以互換的演算法(策略)包裝成一個類別](https://skyyen999.gitbooks.io/-study-design-pattern-in-java/content/strategy.html)  [圖片來源](https://refactoringguru.cn/design-patterns/strategy) 以回合制遊戲為例,每個英雄互相使用技能攻擊對方直到其中一方倒下(每個英雄只能使用一種技能)。 英雄本身只負責自身屬性的維護,然後可以將技能委派出去,建立一個技能介面並將技能封裝進其中,且將攻擊招式方法委派給此介面,也就是在英雄類別中攻擊招式的方法只是呼叫技能介面中的此方法而已,此外將技能介面實作出不同的技能招式,英雄可以切換不同的招式攻擊。 **Advantage** 1. 可以在 runtime 時切換不同的演算法 2. 可將演算法的實現與與使用此演算法的程式碼隔離 3. 使用聚合代替繼承 4. open/close 原則,無須對 Context 修改就能擴增新的策略 **Disadvantage** 1. 如果演算法不太需要修改,使用此模式只會更複雜 2. 要交由使用者來選擇策略,因此需要知道策略之間的差異 ## Reference [Class Diagram 類別圖筆記](https://oscarada87.github.io/2020/10/24/%E9%A1%9E%E5%88%A5%E5%9C%96class%20diagram/) **Factory** [設計模式—工廠與抽象工廠 (Factory & Abstract Factory Design Pattern)](https://medium.com/wenchin-rolls-around/%E8%A8%AD%E8%A8%88%E6%A8%A1%E5%BC%8F-%E5%B7%A5%E5%BB%A0%E8%88%87%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%BB%A0-factory-abstract-factory-design-pattern-8c28d29cb3ac) [【Design Pattern】4:Factory Method Pattern 工廠方法模式 (創造)](https://spicyboyd.blogspot.com/2018/08/design-pattern4factory-method-pattern.html) [設計模式 - 工廠方法及抽象工廠](https://blog.techbridge.cc/2017/05/22/factory-method-and-abstract-factory/) **Builder** [Java 設計模式 建造者模式 Builder Pattern](https://matthung0807.blogspot.com/2019/09/design-pattern-builder-pattern.html) [Java 設計模式——建造者模式(Builder Pattern)](https://www.itread01.com/content/1545052746.html#%E4%B8%89%E3%80%81%E5%B8%B8%E8%A7%81%E7%AC%AC%E4%B8%80%E7%A7%8D%E6%96%B9%E5%BC%8F) **Prototype** [Prototype Pattern -- 複製建立物件個體](http://twmht.github.io/blog/posts/design-pattern/prototype.html) **Singleton** [[Design Pattern] Singleton 單例模式](https://ithelp.ithome.com.tw/articles/10221791) [單例模式 Singleton](https://skyyen999.gitbooks.io/-study-design-pattern-in-java/content/singleton.html) **Adapter** [[Design Pattern] Adapter 配接器模式](https://ithelp.ithome.com.tw/articles/10219666) **Bridge** [Design Pattern: Structural Patterns — Bridge Pattern (橋接模式)](https://medium.com/bucketing/structural-patterns-bridge-pattern-e06e4de5045c) **Composite** [[Design Pattern] Composite 組合模式](https://ithelp.ithome.com.tw/articles/10218208) **Facade** [[Design Pattern] Facade 門面模式](https://ithelp.ithome.com.tw/articles/10227186) [重新整理Facade Pattern](http://teddy-chen-tw.blogspot.com/2013/08/facade-pattern.html) **Template Method** [[Design Pattern] Template 模板模式](https://ithelp.ithome.com.tw/articles/10220163) **Strategy** [[Design Pattern] Strategy 策略模式](https://ithelp.ithome.com.tw/articles/10220739) [Design Pattern 設計之路 (2) - Strategy Pattern 策略模式 你需要一個軍師](https://www.youtube.com/watch?v=IkG_KuMpQRM) ###### tags: `design pattern`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up