設計模式整理列表
以下第一部分是物件導向程式設計基本原則,後面三個部分是設計模式(design pattern)。
基本原則 (1~5 又稱 SOLID)
- 單一職責原則 (SRP:Single Responsibility Principle) 一個類別,應該只有一個引起它變化的原因
- 開放、封閉原則 (OCP:Open Closed Principle) 對於擴展是開放的 (open for extension) 對於修改是封閉的 (closed for modification)
- 里氏(Liskov)代換原則 (LSP:Liskov Substitution Principle) 子類別必須能替換父類別。
- 介面隔離原則 (ISP:Interface Segregation Principle)
- 依賴倒轉原則 (DIP:Dependency Inversion Principle) 抽象不應該依賴細節,細節應該依賴抽像。因為抽像相對較穩定。 高層模組不應該依賴低層模組,兩個都應該依賴抽像。 針對接口編寫程式,不要對具體實現的東西編寫程式。
迪米特法則 (LoD:Law of Demeter) 最少知識原則 Principle of Least Knowledge 只和自己眼前的朋友交談 Only talk to your immediate friends 低耦合
[例如] 郵差送來掛號信,須要蓋收件人印章。 一般人不會叫郵差自己進屋找印章,既浪費時間也不安全。 正常都是自己進屋拿,或是請其他家人幫忙拿。 因為不應該給郵差進屋找東西的權限、郵差也不須要知道印章放在屋內何處。
- 合成/聚合重覆使用原則 (CARP)(Composite/Aggregate Reuse Principle)
多用合成/聚合,少用繼承。
在兩個物件有 has-a (has-parts、is-part-of)關係時 => 合成/聚合 (A has a B)
當兩個物件有 is-a (is-a-kind-of)關係時 => 繼承 (Superman is a kind of Person)
- 合成 (Composite):A、B兩物件有合成關係時,表示其中一個物件消失(ex:書本),另一個物件也會消失(ex:章節)。
- 聚合 (Aggregate):A、B兩物件有聚合關係時,表示其中一個物件消失(ex:球隊),另一個物件不會消失(ex:球員)。
[參考]
http://zh.wikipedia.org/wiki/%E9%A1%9E%E5%88%A5%E5%9C%96 http://antrash.pixnet.net/blog/post/80808873-%E8%AB%96%E7%89%A9%E4%BB%B6%E5%B0%8E%E5%90%91part-9%EF%BC%9A%E8%AA%8D%E8%AD%98is-a%E8%B7%9Fhas-a%E7%9A%84%E5%B7%AE%E7%95%B0%E6%80%A7 http://fengyu0318.sg1003.myweb.hinet.net/ood/classRelationShip.pdf
創建型模式 (Creational Pattern)
簡單工廠模式 (Simple Factory pattern) 使用 class 的靜態方法,依不同條件,取得不同物件,並用取得的物件,做類似的事情。 缺點是要新增不同條件時,須修改到類別的靜態方法。
工廠方法模式 (Factory Method Pattern) 避免了簡單工廠模式,要新增條件時,對工廠類靜態方法的修改(對修改應該是封閉的)。
抽象工廠模式 (Abstract Factory Pattern) 抽象工廠類別,可返回同類型的工廠。這些返回的工廠,有多個相同的方法,做類似的事。
建造者模式(生成器模式) (Builder Pattern) 將某種類的產品建造過程,將生產步驟整理出來, 所有要生產這類產品的 class,均要實現這些標準化步驟。 另外,為避免實際生產時,遺漏某步驟,統一由一個指揮者 class,執行一系列的生產步驟。
原型模式 (Prototype Pattern) 複製一個已存在的物件,來產生新的物件。 淺複製(shallow clone):僅複製舊物件內的屬性,舊物件內的物件不複製。所以新、舊物件會共用這些其他物件。 深複製(deep clone):舊物件內的屬性、參考到的其他物件,都會複製一份。
- 單例模式 (Singleton Pattern) 讓一個類別只能有一個實例(Instance)的方法。 產生單一實例的方式: 懶漢方式(Lazy initialization):第一次使用時,才產生實例。 餓漢方式(Eager initialization):class 載入時就產生實例,不管後面會不會用到。
- 結構型模式 (Structural Pattern)
- 適配器模式 (Adapter Pattern) 某個已存在的類,介面不是用戶所期待的。適配器,則是當做中間的轉接口,以提供用戶期待的介面。 可分成兩種實作方法 Object Adapter Pattern (對象適配器模式):將已存在的類的實例,包裹在適配器類別中。 Class Adapter Pattern (類適配器模式):使用多重繼承。
- 橋接模式 (Bridge Pattern) 將一個物件的具體行為(實作)抽出來,成為一個獨立的物件。 也就是原本的一個物件,變成兩個物件:「抽像物件」+「實作物件」。 優點是抽像物件與實作物件可以解耦合,各自獨立變化。
- 組合模式 (Composite Pattern) 數個物件之間,呈現一種樹狀結構。
- 裝飾模式 (Decorator Pattern) 在某一物件動態加上功能。 一層一層的將功能套上去,每一層執行的是不同的物件。
- 外觀模式 (Facade Pattern) 將原有的大系統包裝起來,用另一個較簡易的介面開放給使用者。 使用者只須瞭解介面的的使用方式。而不須瞭解大系統內,各個小系統的操作方式。
- 享元模式 (Flyweight Pattern) 物件之間,若有共同的部分可以共享,則將可共用的部分獨立為共享物件, 不能共享的部份外部化,使用時再將外部化的部分傳給共享物件。 這樣做的優點是減少記憶體使用量。缺點是程式邏輯可能變得較複雜。
- 代理模式 (Proxy Pattern) 有兩個物件,代理物件、真實物件, 系統使用代理物件操作,代理物件內部則再去操作真實物件。 應用:遠程代理、虛擬代理、安全代理
[參考]
http://zh.wikipedia.org/wiki/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F
- 行為型模式 (Behavioral pattern)
- 責任鏈模式 (Chain-of-responsibility Pattern) 有幾個物件都能處理某種請求,但處理的能範圍(權限)不同, 當這個物件沒有處理的權限時,能夠將這個請求,傳遞給下一個物件繼續處理。
- 命令模式 (Command Pattern) 一般命令包含發出命令和執行命令。 命令模式,則是將這個過程拆成三個物件,發出命令的物件(Invoker)、命令的物件(command)、執行命令的物件(receiver) 由 Invoker 物件,來建造要執行的命令。如此要擴充功能時,例如增加命令重覆執行、取消命令...等,也變得較單純。
- 解釋器模式 (Interpreter Pattern)
用來解釋、直譯一種語言的方法。
[參考]
http://en.wikipedia.org/wiki/Interpreter_pattern http://www.dofactory.com/Patterns/PatternInterpreter.aspx - 迭代器模式 (Iterator Pattern) 遍歷容器裡面元素的一種方法。
- 中介者模式 (Mediator Pattern) 當物件和物件之間或有錯綜複雜的交互作用,可將這些關係交由另一物件(中介者)來處理, 以減少這些物件間的耦合。
- 備忘錄模式 (Memento Pattern) 讓物件回復到之前狀態的方法。
- 觀察者模式 (發佈/訂閱模式) (Observer Pattern)
兩種類型的物件,「通知者」和「觀察者」。
- 訂閱:「通知者」可增減訂閱列表中的「觀察者」
- 發佈:當有監聽的事件發生時,「通知者」可從訂閱列表中,將事件通知「觀察者」,「觀察者」則會對此事件做相對應的動作。
- 功用:解除耦合,讓耦合的雙方依賴抽像(接口),而不依賴具體。
- 狀態模式 (State Pattern) 一物件有多個狀態,在不同狀態下有不同的行為。 一般可能會用多個 if else 來處理這些分支行為。 若使用狀態模式,則是將這些狀態處理,提取出來到另外的 class 處理這些分支。 也就是將 if else 改寫成 class。
- 策略模式 (Strategy Pattern) 將不同的演算法,定義成一個家族, 這些演算法實現同樣的接口,且寫成個別的類別,所以彼此之間能夠互相替換。 優點是以後要增加新的演算法,只須額外新增一個類別,不須動到原本的類別。
- 模板方法模式 (Template Method Pattern) 將不變的部分移到父類別,去除子類別重覆的程式碼
- 訪問者模式 (Visitor Pattern)
當一個「物件結構」中的「元素」幾乎不會異動,但這些「元素的行為」常會增減,則適合用訪問者模式。
訪問者模式是將「元素的行為」,提取出來,每一種行為做成一個 「Visitor(訪問者) 物件」,
每一個 「Visitor(訪問者) 物件」,都能根據原本「物件結構」中不同的「元素」,產生不同行為。
參考:
http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29 (SOLID)
http://en.wikipedia.org/wiki/Software_design_pattern
http://www.dofactory.com/Patterns/Patterns.aspx