- 基本原則 (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 的靜態方法,依不同條件,取得不同物件,並用取得的物件,做類似的事情。
缺點是要新增不同條件時,須修改到類別的靜態方法。
[C# 範例]
- 工廠方法模式 (Factory Method Pattern)
避免了簡單工廠模式,要新增條件時,對工廠類靜態方法的修改(對修改應該是封閉的)。
[C# 範例] - 抽象工廠模式 (Abstract Factory Pattern)
抽象工廠類別,可返回同類型的工廠。這些返回的工廠,有多個相同的方法,做類似的事。
[C# 範例] - 建造者模式(生成器模式) (Builder Pattern)
某種類的產品,有一建造過程,將這些生產步驟整理出來,
所有要生產這類產品的 class,均要實現這些標準化步驟。
另外,為避免實際生產時,遺漏某步驟,統一由一個指揮者 class,執行一系列的生產步驟。
[C# 範例] - 原型模式 (Prototype Pattern)
複製一個已存在的物件,來產生新的物件。
淺複製(shallow clone):僅複製舊物件內的屬性,舊物件內的物件不複製。所以新、舊物件會共用這些其他物件。
深複製(deep clone):舊物件內的屬性、參考到的其他物件,都會複製一份。 - 單例模式 (Singleton Pattern)
讓一個類別只能有一個實例(Instance)的方法。
產生單一實例的方式:
懶漢方式(Lazy initialization):第一次使用時,才產生實例。
餓漢方式(Eager initialization):class 載入時就產生實例,不管後面會不會用到。
[C# 範例] - 結構型模式 (Structural Pattern)
- 適配器模式 (Adapter Pattern)
某個已存在的類,介面不是用戶所期待的。適配器,則是當做中間的轉接口,以提供用戶期待的介面。
可分成兩種實作方法
Object Adapter Pattern (對象適配器模式):將已存在的類的實例,包裹在適配器類別中。
Class Adapter Pattern (類適配器模式):使用多重繼承。 - 橋接模式 (Bridge Pattern)
將一個物件的具體行為(實作)抽出來,成為一個獨立的物件。
也就是原本的一個物件,變成兩個物件:「抽像物件」+「實作物件」。
優點是抽像物件與實作物件可以解耦合,各自獨立變化。
[C# 範例] - 組合模式 (Composite Pattern)
數個物件之間,呈現一種樹狀結構。
[C# 範例] - 裝飾模式 (Decorator Pattern)
在某一物件動態加上功能。
一層一層的將功能套上去,每一層執行的是不同的物件。
[C# 範例] - 外觀模式 (Facade Pattern)
將原有的大系統包裝起來,用另一個較簡易的介面開放給使用者。
使用者只須了解介面的的使用方式。而不須了解大系統內,各個小系統的操作方式。 - 享元模式 (Flyweight Pattern)
物件之間,若有共同的部分可以共享,則將可共用的部分獨立為共享物件,
不能共享的部份外部化,使用時再將外部化的部分傳給共享物件。
這樣做的優點是減少記憶體使用量。缺點是程式邏輯可能變得較複雜。
[C# 範例] - 代理模式 (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)
有幾個物件都能處理某種請求,但處理的範圍(權限)不同,
當這個物件沒有處理的權限時,能夠將這個請求,傳遞給下一個物件繼續處理。
[C# 範例] - 命令模式 (Command Pattern)
一般命令包含發出命令和執行命令。
命令模式,則是將這個過程拆成三個物件,發出命令的物件(Invoker)、命令的物件(command)、執行命令的物件(receiver)
由 Invoker 物件,來建造要執行的命令。如此要擴充功能時,例如增加命令重覆執行、取消命令...等,也變得較單純。
[C# 範例] - 解釋器模式 (Interpreter Pattern)
用來解釋、直譯一種語言的方法。
[C# 範例]
[參考]
http://en.wikipedia.org/wiki/Interpreter_pattern
http://www.dofactory.com/Patterns/PatternInterpreter.aspx - 迭代器模式 (Iterator Pattern)
遍歷容器裡面元素的一種方法。 - 中介者模式 (Mediator Pattern)
當物件和物件之間或有錯綜複雜的交互作用,可將這些關係交由另一物件(中介者)來處理,
以減少這些物件間的耦合。
[C# 範例] - 備忘錄模式 (Memento Pattern)
讓物件回復到之前狀態的方法。
[C# 範例] - 觀察者模式 (發佈/訂閱模式) (Observer Pattern)
兩種類型的物件,「通知者」和「觀察者」。
訂閱:「通知者」可增減訂閱列表中的「觀察者」
發佈:當有監聽的事件發生時,「通知者」可從訂閱列表中,將事件通知「觀察者」,「觀察者」則會對此事件做相對應的動作。
功用:解除耦合,讓耦合的雙方依賴抽像(接口),而不依賴具體。
[C# 範例] - 狀態模式 (State Pattern)
一物件有多個狀態,在不同狀態下有不同的行為。
一般可能會用多個 if else 來處理這些分支行為。
若使用狀態模式,則是將這些狀態處理,提取出來到另外的 class 處理這些分支。
也就是將 if else 改寫成 class。
[C# 範例] - 策略模式 (Strategy Pattern)
將不同的演算法,定義成一個家族,
這些演算法實現同樣的接口,且寫成個別的類別,所以彼此之間能夠互相替換。
優點是以後要增加新的演算法,只須額外新增一個類別,不須動到原本的類別。
[C# 範例] - 模板方法模式 (Template Method Pattern)
將不變的部分移到父類別,去除子類別重覆的程式碼
- 訪問者模式 (Visitor Pattern)
當一個「物件結構」中的「元素」幾乎不會異動,但這些「元素的行為」常會增減,則適合用訪問者模式。
訪問者模式是將「元素的行為」,提取出來,每一種行為做成一個 「Visitor(訪問者) 物件」,
每一個 「Visitor(訪問者) 物件」,都能根據原本「物件結構」中不同的「元素」,產生不同行為。
[C# 範例]
- 責任鏈模式 (Chain-of-responsibility Pattern)
參考:
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
感謝版主的用心,這是我看到最好的設計模式整理文,用詞精煉明白,不像有些「造神」blog,術語一堆又不知所云。
回覆刪除太感動了,本來我還怕寫得太簡略 :)
刪除太棒了,能夠精確明白地說明複雜的抽象原理才是我們程式人的風骨!
刪除可惜職場上的風氣反而是鼓勵背誦一堆術語,把實際上簡單到不行的原理描述到大家都聽不懂,才叫專業......
寫的很棒哦~~ 很精簡易懂
回覆刪除感謝大大無私的分享 我真的受益良多啊啊啊啊
回覆刪除其他受益的人不該吝嗇留言 要多多鼓勵啊啊啊
謝謝您的鼓勵,很高興有幫到您 :)
刪除這是我目前看過最棒的設計模式教學了....簡單易懂
回覆刪除請問同一個專案,設計模式通常會用同一種嗎?
回覆刪除我自己是覺得不一定,畢竟設計模式只是處理方法,
刪除要用那些處理方法,我習慣評估可維護性、未來擴充性、性能、開發所需時間來衡量。
其中未來我覺得最難評估,有時考慮太多,最後都沒用到,反而造成無謂的過度設計。
至於有些類似的系統,可能因外在因素影響(例如使用人數),假如會很多人用,就很注重寫法的性能差異,但只有少數人用,性能差異感覺不到,寫法又有更多選擇。
作者寫的真的很好,非常適合新手看
回覆刪除感謝版主受益良多!
回覆刪除寫得很好~受益良多~讚
回覆刪除這真的是看過講的最清楚的設計模式教學~讚!!
回覆刪除