【白話設計模式二十五】臨別總結:設計模式與7大原則

#0 系列目錄#算法

#1 建立型模式#編程

  1. 簡單工廠模式(Simple factory pattern): 提供一個建立對象實例的功能,而無需關心具體的實現。被建立實例的類能夠是接口、抽象類,也能夠是具體的類。設計模式

  2. 工廠方法模式(Factory method pattern): 定義了一個建立對象的接口, 但由子類決定要實例化的類是哪個。工廠方法讓類把實例化推遲到子類。框架

  3. 抽象工廠模式(Abstract factory pattern): 提供一個接口, 用於建立相關或依賴對象的家族, 而不須要指定具體類函數

  4. 生成器模式(Builder pattern): 使用生成器模式封裝一個產品的構造過程, 並容許按步驟構造。將一個複雜對象的構建與它的表示分離, 使得一樣的構建過程能夠建立不一樣的表示。性能

  5. 原型模式(Prototype pattern): 當建立給定類的實例過程很昂貴或很複雜時, 就使用原形模式。學習

  6. 單例模式(Singleton pattern): 確保一個類只有一個實例, 並提供全局訪問點。ui

#2 結構型模式#.net

  1. 適配器模式(Adapter pattern): 將一個類的接口, 轉換成客戶指望的另外一個接口。適配器讓本來接口不兼容的類能夠合做無間。對象適配器使用組合, 類適配器使用多重繼承。設計

  2. 橋接模式(Bridge pattern): 使用橋接模式經過將實現和抽象放在兩個不一樣的類層次中而使它們能夠獨立改變

  3. 組合模式(Composite pattern): 容許你將對象組合成樹形結構來表現"總體/部分"層次結構。組合能讓客戶以一致的方式處理個別對象以及對象組合

  4. 裝飾者模式(Decorator pattern): 動態地將責任附加到對象上, 若要擴展功能, 裝飾者提供了比繼承更有彈性的替代方案。

  5. 外觀模式(Facade pattern): 提供了一個統一的接口, 用來訪問子系統中的一羣接口。外觀定義了一個高層接口, 讓子系統更容易使用。

  6. 亨元模式(Flyweight Pattern): 如想讓某個類的一個實例能用來提供許多"虛擬實例", 就使用蠅量模式。

  7. 代理模式(Proxy pattern): 爲另外一個對象提供一個替身或佔位符以控制對這個對象的訪問

#3 行爲型模式#

  1. 責任鏈模式(Chain of responsibility pattern): 經過責任鏈模式, 你能夠爲某個請求建立一個對象鏈。每一個對象依序檢查此請求並對其進行處理或者將它傳給鏈中的下一個對象。

  2. 命令模式(Command pattern): 將"請求"封閉成對象, 以便使用不一樣的請求,隊列或者日誌來參數化其餘對象. 命令模式也支持可撤銷的操做。

  3. 解釋器模式(Interpreter pattern): 使用解釋器模式爲語言建立解釋器

  4. 迭代器模式(Iterator pattern): 提供一種方法順序訪問一個聚合對象中的各個元素, 而又不暴露其內部的表示。

  5. 中介者模式(Mediator pattern) : 使用中介者模式來集中相關對象之間複雜的溝通和控制方式。

  6. 備忘錄模式(Memento pattern): 當你須要讓對象返回以前的狀態時(例如, 你的用戶請求"撤銷"), 你使用備忘錄模式。

  7. 觀察者模式(Observer pattern): 在對象之間定義一對多的依賴, 這樣一來, 當一個對象改變狀態, 依賴它的對象都會收到通知, 並自動更新

  8. 狀態模式(State pattern): 容許對象在內部狀態改變時改變它的行爲, 對象看起來好象改了它的類。

  9. 策略模式(Strategy pattern): 定義了算法族, 分別封閉起來, 讓它們之間能夠互相替換, 此模式讓算法的變化獨立於使用算法的客戶。

  10. 模板方法模式(Template pattern): 在一個方法中定義一個算法的骨架, 而將一些步驟延遲到子類中. 模板方法使得子類能夠在不改變算法結構的狀況下, 從新定義算法中的某些步驟。

  11. 訪問者模式(Visitor pattern): 當你想要爲一個對象的組合增長新的能力, 且封裝並不重要時, 就使用訪問者模式

#4 設計模式和設計原則# ##4.1 設計模式和設計原則的關係## 面向對象的分析設計有不少原則,這些原則大都從思想層面,給咱們指出了面向對象分析設計的正確方向,是咱們進行面向對象分析設計應該盡力遵照的準則。

而設計模式已是針對某個場景下某些問題的某個解決方案。也就是說這些設計原則是思想上的指導,而設計模式是實現上的手段,所以設計模式也是應該遵照這些原則的,換句話說,設計模式就是這些設計原則的一些具體體現

##4.2 爲什麼不重點講設計原則## 既然設計模式是這些設計原則的具體體現,那也就意味着設計模式的思想上的根就是這些設計原則了,沒錯,能夠這麼認爲。這樣一來,有些朋友就會很疑惑了,那麼爲什麼不重點講講設計原則呢?對於這個問題,咱們有以下的考慮:

設計原則自己是從思想層面上進行指導,自己是高度歸納和原則性的,只是一個設計上的大致方向,其具體實現並非只有設計模式這一種。理論上來講,能夠在相同的原則指導下,作出不少不一樣的實現來。

每一種設計模式並非單一的體現某一個設計原則,事實上,不少設計模式都是融合了不少個設計原則的思想,並很差特別強調設計模式對某個或者是某些設計原則的體現。並且每一個設計模式在應用的時候也會有不少的考量,不一樣使用場景下,突出體現的設計原則也多是不同的。

這些設計原則只是一個建議指導,事實上,在實際開發中,不多作到徹底遵照,老是在有意無心的違反一些或者是部分設計原則。設計工做原本就是一個不斷權衡的工做,有句話說得很好:「設計是一種危險的平衡藝術」,設計原則只是一個指導,有些時候,還要綜合考慮業務功能、實現的難度、系統性能、時間與空間等不少方面的問題。

設計模式自己已經很複雜了,已經很難再去深刻的探討這些設計原則,這樣也避免出現過多的重點內容,致使你們無所適從。

#5 常見的面向對象設計原則# ##5.1 單一職責原則SRP(Single Responsibility Principle)## 所謂單一職責原則,指的就是:一個類應該僅有一個引發它變化的緣由。

這裏變化的緣由就是所說的「職責」,若是一個類有多個引發它變化的緣由,那麼也就意味着這個類有多個職責,再進一步說,就是把多個職責耦合在一塊兒了。

這會形成職責的相互影響,可能一個職責的變化,會影響到其它職責的實現,甚至引發其它職責跟着變化,這種設計是很脆弱的。

這個原則看起來是最簡單和最好理解的,可是其實是很難徹底作到的,難點在於如何區分這個「職責」,這是個沒有標準量化的東西,哪些算職責,到底這個職責有多大的粒度,這個職責如何細化等等。所以,在實際開發中,這個原則也是最容易違反的。

##5.2 開放-關閉原則OCP(Open-Closed Principle)## 所謂開放-關閉原則,指的就是:一個類應該對擴展開放,對修改關閉。通常也被簡稱爲開閉原則,開閉原則是設計中很是核心的一個原則。

開閉原則要求的是,類的行爲是能夠擴展的,並且是在不修改已有的代碼的狀況下進行擴展,也沒必要改動已有的源代碼或者二進制代碼。

看起來好像是矛盾的,怎麼樣才能實現呢?

實現開閉原則的關鍵就在於合理的抽象,分離出變化與不變化的部分,爲變化的部分預留下可擴展的方式,好比:鉤子方法、或是動態組合對象等等。

這個原則看起來也很簡單,但事實上,一個系統要所有作到遵照開閉原則,幾乎是不可能的,也沒這個必要。適度的抽象能夠提升系統的靈活性,使其可擴展、可維護,可是過分的抽象,會大大增長系統的複雜程度。應該在須要改變的地方應用開閉原則就能夠了,而不用處處使用,從而陷入過分設計。

##5.3 里氏替換原則LSP(Liskov Substitution Principle)## 所謂里氏替換原則,指的就是:子類型必須可以替換掉它們的父類型。這很明顯是一種多態的使用狀況,它能夠避免在多態的應用中,出現某些隱蔽的錯誤。

事實上,當一個類繼承了另一個類,那麼子類就擁有了父類中能夠繼承下來的屬性和操做,理論上來講,此時使用子類型去替換掉父類型,應該不會引發原來使用父類型的程序出現錯誤。

可是,很不幸的是,在某些狀況下是會出現問題的,好比:若是子類型覆蓋了父類型的某些方法,或者是子類型修改了父類型某些屬性的值,那麼原來使用父類型的程序就可能會出現錯誤,由於在運行期間,從表面上看,它調用的是父類型的方法,須要的是父類型方法實現的功能,可是實際運行調用的確是子類型覆蓋實現的方法,而該方法跟父類型的方法並不同,那就會致使錯誤的產生

從另一個角度來講,里氏替換原則是實現開閉的主要原則之一,開閉原則要求對擴展開放,擴展的一個實現手段就是使用繼承,而里氏替換原則是保證子類型可以正確替換父類型,只有能正確替換,才能實現擴展,不然擴展了也會出現錯誤

##5.4 依賴倒置原則DIP(Dependence Inversion Principle)## 所謂依賴倒置原則,指的就是:要依賴於抽象,不要依賴於具體類。要作到依賴倒置,典型的應該作到:

高層模塊不該該依賴於底層模塊,兩者都應該依賴於抽象;

抽象不該該依賴於具體實現,具體實現應該依賴於抽象;

不少人以爲,層次化調用的時候,應該是高層調用「底層所擁有的接口」,這是一種典型的誤解。事實上,通常高層模塊包含對業務功能的處理和業務策略選擇,應該被重用,應該是高層模塊去影響底層的具體實現

所以,這個底層的接口,應該是由高層提出的,而後由底層實現的,也就是說底層的接口的全部權在高層模塊,所以是一種全部權的倒置

倒置接口全部權,這就是著名的Hollywood(好萊塢)原則:不要找咱們,咱們會聯繫你

##5.5 接口隔離原則ISP(Interface Segregation Principle)## 所謂接口隔離原則,指的就是:不該該強迫客戶依賴於他們不用的方法。

這個原則用來處理那些比較「龐大」的接口,這種接口一般會有較多的操做聲明,涉及到不少的職責。客戶在使用這樣的接口的時候,一般會有不少它不須要的方法,這些方法對於客戶來說,就是一種接口污染,至關於強迫用戶在一大堆「垃圾方法」裏面去尋找他須要的方法

所以,這樣的接口應該被分離,應該按照不一樣的客戶須要來分離成爲針對客戶的接口,這樣的接口裏面,只包含客戶須要的操做聲明,這樣既方便了客戶的使用,也能夠避免因誤用接口而致使的錯誤。

分離接口的方式,除了直接進行代碼分離以外,還可使用委託來分離接口,在可以支持多重繼承的語言裏面,還能夠採用多重繼承的方式進行分離。

##5.6 最少知識原則(Least Knowledge Principle)## 所謂最少知識原則,指的就是:只和你的朋友談話。

這個原則用來指導咱們在設計系統的時候,應該儘可能減小對象之間的交互,對象只和本身的朋友談話,也就是隻和本身的朋友交互,從而鬆散類之間的耦合。經過鬆散類之間的耦合來下降類之間的相互依賴,這樣在修改系統的某一個部分時候,就不會影響其它的部分,從而使得系統具備更好的可維護性。

那麼究竟哪些對象才能被看成朋友呢?最少知識原則提供了一些指導:

當前對象自己;

經過方法的參數傳遞進來的對象;

當前對象所建立的對象;

當前對象的實例變量所引用的對象;

方法內所建立或實例化的對象;

總之,最少知識原則要求咱們的方法調用,必須保持在必定的界限範圍以內,儘可能減小對象的依賴關係

##5.7 其它原則## 除了上面提到的這些原則,還有一些你們都熟知的原則,好比:

面向接口編程;

優先使用組合/聚合,而非繼承;

固然也還有不少你們不是很熟悉的原則,好比:

一個類須要的數據應該隱藏在類的內部;

類之間應該零耦合,或者只有傳導耦合,換句話說,類之間要麼沒有關係,要麼只使用另外一個類的接口提供的操做;

在水平方向上儘量統一的分佈系統功能;

#6 設計原則總結#

  1. 單一職責原則【SINGLE RESPONSIBILITY PRINCIPLE】:一個類負責一項職責。

  2. 里氏替換原則【LISKOV SUBSTITUTION PRINCIPLE】:繼承與派生的規則。

  3. 依賴倒置原則【DEPENDENCE INVERSION PRINCIPLE】:高層模塊不該該依賴低層模塊,兩者都應該依賴其抽象;抽象不該該依賴細節;細節應該依賴抽象。即針對接口編程,不要針對實現編程。

  4. 接口隔離原則【INTERFACE SEGREGATION PRINCIPLE】:創建單一接口,不要創建龐大臃腫的接口,儘可能細化接口,接口中的方法儘可能少。

  5. 迪米特法則【LOW OF DEMETER】:低耦合,高內聚。

  6. 開閉原則【OPEN CLOSE PRINCIPLE】:一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。

  7. 組合/聚合複用原則【Composition/Aggregation Reuse Principle(CARP)】:儘可能使用組合和聚合少使用繼承的關係來達到複用的原則。

#7 不是結束而是新的開始# 到此,設計模式系列已經講完結束了,但偏偏相反,要想在設計上更進一步的話,困難纔剛剛開始。更多的是須要思考和領悟,其難度比從入門到中級要大得多。

所以對你而言,看完本系列並非學習的結束,而是新的開始。

##7.1 你該怎麼作## 若是已經深刻領會和掌握了本書的內容,還想要在設計模式上繼續精進的朋友,給出以下的建議:

  1. 多看

多搜尋一些應用設計模式的實際項目、工程或是框架,參考別人的成功應用,再結合本身的經驗來思考和使用。固然項目不該該太大,太大了很難徹底看懂;也不能過小,過小了,沒有太大實用價值,尤爲是沒法參考多個模式綜合應用的狀況,幫助就不大了。

  1. 多練

多尋找機會,把這些設計模式在實際應用中使用,只有親自動手去試驗和使用,才能真正掌握和領會設計模式的精髓。

  1. 多總結

認真分析每次對設計模式的使用是否得當,有什麼經驗和教訓,是否有變形使用的狀況,在不斷總結中進步。

  1. 反覆參閱本系列

理論聯繫實際,經過實際應用反過來加深對理論的理解,以達到融會貫通這些設計模式的知識。所以,你須要反覆參閱本系列,而後實踐,而後再回頭看系列上的知識,你會有不同的體會和領悟。

  1. 多思考

多從設計上去思考這些設計模式,考慮它的設計意圖、設計思想、解決問題的方式、實現的原理、模式的本質、以及如何變形使用等等。

相關文章
相關標籤/搜索