設計模式學習

634828354發表於2017-05-21

作者:Pickle

設計模式總結

  設計模式(Design Patterns)是可複用物件導向軟體的基礎,是一套被反覆使用、多數人知曉的、經過分類編目的、程式碼設計經驗的總結。使用設計模式是為了可重用程式碼,讓程式碼更容易被他人理解、保證程式碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的,設計模式使程式碼編制真正工程化,設計模式是軟體工程的基石,如同大廈的一塊塊磚石一樣。專案中合理的運用設計模式可以完美的解決很多問題,每種模式在現在中都有相應的原理來與之對應,每一個模式描述了一個在我們周圍不斷重複發生的問題,以及該問題的核心解決方案,這也是它能被廣泛應用的原因。

 

一. 首先看看設計模式的分類:

  總體來說設計模式分為三大類:

  建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。

  結構型模式,共七種:介面卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。

  行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代器模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式。

  其他模式:併發型模式和執行緒池模式。

二. 設計模式中用到的設計原則

1.開閉原則(Open Close Principle)

  開閉原則說的是對擴充套件開放,對修改關閉。按照開閉原則在程式程式碼需要進行擴充套件的時候不能對原有的程式進行修改而是要對程式實現熱插拔的效果。
這樣一來程式的易複用和可擴充套件性就能得到大大提升。

2.里氏代換原則(Liskov Substitution Principle)

  里氏代換原則(LSP)中說,任何基類出現的地方,子類一定可以出現。LSP是繼承複用的基石,只有當擴充套件類可以替換掉基類,軟體的單位不受到影響時,基類才能真正的被複用,而擴充套件類也能夠在基類的基礎上增加新的行為。LSP是開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化。而基類與擴充套件類的繼承關係就是抽象化的具體實現。所以LSP是對實現抽象化的具體步驟的規範。

3. 依賴倒轉原則(Dependence Inversion Principle)

  依賴倒轉原則是開閉原則的基礎,具體是說要針對介面程式設計而不是針對具體實現程式設計。為互動物件之間的松耦合設計而努力。

4. 介面隔離原則(Interface Segregation Principle)

  介面隔離原則是說要使用多個隔離的介面,而不要使用單個介面。其作用是降低物件之間的耦合度。

5. 迪米特法則(Demeter Principle)

  迪米特法則也叫最少知道原則。意思是物件之間應該儘量少的知道對方的資訊。使得物件之間在一定程度上是相對獨立的,作用也是降低物件之間的依賴程度。

6. 合成複用原則(Composite Reuse Principle)

  意思就是多用組合少用繼承。 更加靈活易於變化。

  設計模式原則小結:

  其實以上提到的各種原則目標大概只有一個:降低物件之間的耦合,增加程式的可複用性、可擴充套件性、可維護性。設計模式就是軟體設計的一種思想,從大型軟體架構出發,為了可複用和可升級而努力。

三. 常用的23中設計模式

1. 策略模式(Strategy Pattern)

  策略模式封裝了一系列的演算法策略族,這些策略是獨立於客戶的,並且這些策略是可以互換的。客戶透過上下文互動類就可以只呼叫一個執行策略方法就可以呼叫任何一個策略的實現並且可以在不同的策略之間切換。

  對策略模式的詳細介紹:

  http://www.cnblogs.com/wxisme/p/4497535.html

2. 工廠模式 (Factory Pattern)
  工廠模式有3種。簡單工廠模式、工廠方法模式、抽象工廠模式。

  簡單工廠模式:

    簡單工廠模式也叫靜態工廠模式,工廠類一般使用靜態方法 透過接收的引數不同來返回不同的物件例項。但是對增加新產品無能為力,不增加程式碼無法擴充套件。

  工廠方法模式:

    避免了簡單工廠的缺點,滿足了OCP(開閉原則,對擴充套件開放,對修改關閉)原則。簡單工廠只有一個工廠類,而工廠方法有一組實現了相同介面的工廠方法。

  工廠方法模式的缺點:結構和程式碼複雜度高,但是可擴充套件性好,客戶端程式設計難度小。綜合考慮,簡單工廠模式,簡單有一定的可擴充套件性。實際上簡單工廠模式用的多。

    抽象工廠模式:

  抽象工廠模式可以增加產品族,但是不可以增加新產品。縱向擴充套件。抽象工廠模式的用意為:給客戶端提供一個介面,可以建立多個產品族中的產品物件。 關於工廠模式的詳細介紹:

    http://www.cnblogs.com/wxisme/p/4518599.html

    http://www.cnblogs.com/poissonnotes/archive/2010/12/01/1893871.html

3. 單例模式 (Singleton Pattern)

  單例模式保證了一個類在同一時間內JVM中只有一個例項化物件存在。單例模式確保一個類只有一個例項,並只提供一個全域性訪問點。單例模式的意義在於它可以保證只有一個例項化物件,在一定情況下可以降低系統開銷,對於只能有一個例項的類來說保證了系統的穩定性和安全性。
  單例模式的實現方式主要有:餓漢式、懶漢式、雙重檢測鎖、靜態內部類、列舉。

  關於單例模式的具體實現和詳細介紹:

http://www.cnblogs.com/wxisme/p/4517343.html

4. 建造者模式 (Constructor Pattern)

  工廠類模式提供的是建立單個類的模式,而建造者模式則是將各種產品集中起來進行管理,用來建立複合物件,所謂複合物件就是指某個類具有不同的屬性。建造者模式的意義在於實現了構建和裝配的解耦,實現了構建演算法和裝配演算法的解耦,使用於構建過程複雜的情況。

  關於建造者模式的例子:

http://www.cnblogs.com/wxisme/p/4520998.html

5. 原型模式 (Prototype Pattern)

  原型模式只要用來實現物件的複製,對於建立或者複製一個物件的例項非常複雜的時候就可以使用原型模式來複製。在一個複雜的物件中往往還有其他的物件屬性,這樣如果直接複製將導致兩個物件中的物件屬性實際上是指向同一個屬性例項的。這就需要進行深度克隆。實現深度克隆的方法有兩種一種是實現Cloneable介面,重寫clone()方法,另一種是透過序列化反序列化來獲取物件的複製。

關於原型模式的例子:

http://www.cnblogs.com/wxisme/p/4540634.html

6. 介面卡模式 (Adaptor  Pattern)

  介面卡模式將一個介面轉換成客戶期望的另一個介面,目的是次消除由於介面不匹配導致的相容性問題。主要分為三類:類的介面卡模式、物件的適配器模式、介面的介面卡模式。介面卡也可以說成介面與介面之間的轉換器。介面卡的一個典型的應用是:JavaIO中的轉換流,可以將位元組流轉換成字元流,是流的介面卡。

關於介面卡模式的例子:

http://www.cnblogs.com/wxisme/p/4522632.html

7. 裝飾模式 (Decorator Pattern)

  裝飾器模式:動態地給一個物件新增一些額外的職責或者行為。就增加功能來說, Decorator模式相比生成子類更為靈活。裝飾器模式提供了改變子類的靈活方案。裝飾器模式在不必改變原類檔案和使用繼承的情況下,動態的擴充套件一個物件的功能。它是透過建立一個包裝物件,也就是裝飾來包裹真實的物件。

使用裝飾器模式,可以避免程式碼重複和具體子類數量的增加。

關於裝飾模式的例子與解釋:

http://www.cnblogs.com/wxisme/p/4510852.html

8. 代理模式 (Proxy Pattern)

  代理模式是常用的java設計模式,他的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後處理訊息等。代理類與委託類之間通常會存在關聯關係,一個代理類的物件與一個委託類的物件關聯,代理類的物件本身並不真正實現服務,而是透過呼叫委託類的物件的相關方法,來提供特定的服務。 按照代理的建立時期,代理類可以分為兩種。 靜態代理:由程式設計師建立或特定工具自動生成原始碼,再對其編譯。在程式執行前,代理類的.class檔案就已經存在了。 動態代理:在程式執行時,運用反射機制動態建立而成。 

更多介紹:

http://www.cnblogs.com/wxisme/p/4550574.html

9.外觀模式 (Facade Pattern)

  外觀模式提供了一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更容易使用。簡單的說,外觀模式就是把複雜的系統的具體操作封裝起來,只暴露一個簡單的介面,做和眾多子系統之間松耦合。外觀模式是為了解決類與類之家的依賴關係的,像spring一樣,可以將類和類之間的關係配置到配置檔案中,而外觀模式就是將他們的關係放在一個Facade類中,降低了類類之間的耦合度。

關於外觀模式的例子:

http://www.cnblogs.com/wxisme/p/4541085.html

10.橋接模式(Bridge Pattern)

  橋接模式就是把事物和其具體實現分開,使他們可以各自獨立的變化。橋接的用意是:將抽象化與實現化解耦,使得二者可以獨立變化。這樣一來兩個維度之間就可以任意的擴充套件和變化而不影響對方。橋接模式極大的提高了系統的可擴充套件性,可以大大降低維護的成本。

關於橋接模式:

http://www.cnblogs.com/wxisme/p/4553362.html

11. 享元模式(Flyweight Pattern)

  享元模式的主要目的是實現物件的共享,即共享池,當系統中物件多的時候可以減少記憶體的開銷,通常與工廠模式一起使用。FlyWeightFactory負責創建和管理享元單元,當一個客戶端請求時,工廠需要檢查當前物件池中是否有符合條件的物件,如果有,就返回已經存在的物件,如果沒有,則建立一個新物件,FlyWeight是超類。一提到共享池,我們很容易聯想到Java裡面的JDBC連線池,想想每個連線的特點,我們不難總結出:適用於作共享的一些個物件,他們有一些共有的屬性,就拿資料庫連線池來說,url、driverClassName、username、password及dbname,這些屬性對於每個連線來說都是一樣的,所以就適合用享元模式來處理,建一個工廠類,將上述類似屬性作為內部資料,其它的作為外部資料,在方法呼叫時,當做引數傳進來,這樣就節省了空間,減少了例項的數量。

關於享元模式的例子:

http://www.cnblogs.com/wxisme/p/4549858.html

12. 模板方法模式(Template Method Pattern)

  模板方法模式是程式設計中經常用到的模式,它定義了一個操 作中的演算法骨架,將某些步驟延遲到子類中實現。這樣,新的子類可以在 不改變一個演算法結構的前提下重新定義該演算法的某些特定的步驟。處理某個流程的程式碼已經都具備,但是其中某個節點的程式碼暫時不 能確定。因此採用工廠方法模式將這個節點的程式碼實現轉移給子類完成 即:處理步驟父類中定義好,具體實現延遲到子類中定義。 模板方法模式的使用場景:實現一個演算法時,整體步驟很固定。但是某些部分易變。易變部分可以抽象出來,供子類實現。

模板方法模式的具體例子:

http://www.cnblogs.com/wxisme/p/4540600.html

13. 觀察者模式(Observer Pattern)

  觀察者模式定義了物件之間的一對多的依賴,這樣一來,當一個狀態發生變化時,它的所有依賴者都會收到通知並自動更新。;類似於郵件的訂閱一樣當一個使用者訂閱了某個主題時,每當主題有變化或者更新的時候都會通知訂閱的使用者,當然這種訂閱可以註冊也可以登出。同樣和電子郵件一樣,訂閱也有推送式和拉取式,就像SMTP協議和POP3協議一樣。

關於觀察者模式的例子:

http://www.cnblogs.com/wxisme/p/4499147.html

14. 迭代器模式(Iterator Pattern)

  迭代器模式非常好理解就是提供一種功能來遍歷一個集合容器,不管是C++還是Java都在集合容器裡提供了一種遍歷各種容器的迭代器,Java中還內建了Iterator介面。

關於迭代器模式的例子:

http://www.cnblogs.com/wxisme/p/4541008.html

15. 責任鏈模式(Chain of Responsibility)

  責任鏈模式是一種物件的行為模式。在責任鏈模式裡,很多物件由每一個物件對其下家的引用而連線起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個物件決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織和分配責任。說到責任鏈模式我想到了多功能的連結串列,還有DNS的遞迴解析方式。好像都是責任鏈。

責任鏈的例子:

http://www.cnblogs.com/wxisme/p/4550712.html

16. 命令模式(Command Pattern)

  命令模式就是將一個請求封裝為一個物件,從而使我們可以用不同的請求對客戶進行引數化,對請求排隊或者記錄請求日誌,以及支援可撤銷的操作。也稱之為:動作模式,事務模式。簡單的說命令模式將命令的發出者、命令的傳遞者、命令的執行者獨立出來,滿足了松耦合的要求,易於維護和更改。

命令模式的例子:

http://www.cnblogs.com/wxisme/p/4540588.html

17. 備忘錄模式(Memento Pattern)

  備忘錄物件是一個用來儲存另外一個物件內部狀態的快照的物件。備忘錄模式的用意是在不破壞封裝的條件下,將一個物件的狀態捕捉(Capture)住,並外部化,儲存起來,從而可以在將來合適的時候把這個物件還原到儲存起來的狀態。備忘錄模式常常與命令模式和迭代子模式一同使用。簡單的說備忘錄模式就是在必要的時候可以恢復到物件的某一個狀態。對物件的備忘其實就是對這個物件某個狀態的深度複製。這讓我想起了原型模式。等等我還想起了DBMS中事務的撤銷和資料恢復還有DBMS的日誌備份系統。

關於備忘錄模式的例子:

http://www.cnblogs.com/wxisme/p/4540682.html

18. 狀態模式(State Pattern)

  狀態模式,又稱狀態物件模式(Pattern of Objects for States),狀態模式是物件的行為模式。狀態模式允許一個物件在其內部狀態改變的時候改變其行為。這個物件看上去就像是改變了它的類一樣。狀態模式可以讓物件在不同的狀態之間切換,並且隨著物件狀態的改變其行為也跟著改變。
關於狀態模式的例子:

http://www.cnblogs.com/wxisme/p/4544432.html

19. 訪問者模式(Visitor Pattern)

  訪問者模式把資料結構和作用於結構上的操作解耦合,使得操作集合可相對自由地演化。訪問者模式適用於資料結構相對穩定演算法又易變化的系統。因為訪問者模式使得演算法操作增加變得容易。若系統資料結構物件易於變化,經常有新的資料物件增加進來,則不適合使用訪問者模式。訪問者模式的優點是增加操作很容易,因為增加操作意味著增加新的訪問者。訪問者模式將有關行為集中到一個訪問者物件中,其改變不影響系統資料結構。其缺點就是增加新的資料結構很困難。

訪問者模式的詳細介紹:

http://www.cnblogs.com/java-my-life/archive/2012/06/14/2545381.html

20. 中介者模式(Mediator Pattern)

  中介者模式是物件的行為模式。中介者模式包裝了一系列物件相互作用的方式,使得這些物件不必相互明顯引用。從而使它們可以較鬆散地耦合。當這些物件中的某些物件之間的相互作用發生改變時,不會立即影響到其他的一些物件之間的相互作用。從而保證這些相互作用可以彼此獨立地變化。中介者模式就是把物件之間的複雜網狀關聯結構化解成星形結構使得物件之間解耦。

關於中介者模式的詳細舉例:

http://www.cnblogs.com/wxisme/p/4546723.html

http://www.cnblogs.com/java-my-life/archive/2012/06/20/2554024.html

21. 直譯器模式(Interpreter Pattern)

  直譯器模式是類的行為模式。給定一個語言之後,直譯器模式可以定義出其文法的一種表示,並同時提供一個直譯器。客戶端可以使用這個直譯器來解釋這個語言中的句子。直譯器模式在大多數情況下是用不到的。直譯器模式中有一個Context上下文類用來獲取要解析語句的輸入流。每個表示式類中有一個interpret(Context c)方法用來解析語句的語義並返回正確的結果。

關於直譯器模式請看:

http://www.cnblogs.com/java-my-life/archive/2012/06/19/2552617.html

22. 組合模式(Composite Pattern)

  組合模式,將物件組合成樹形結構以表示“部分-整體”的層次結構,組合模式使得使用者對單個物件和組合物件的使用具有一致性。有時候又叫做部分-整體模式,它使我們樹型結構的問題中,模糊了簡單元素和複雜元素的概念,客戶程式可以像處理簡單元素一樣來處理複雜元素,從而使得客戶程式與複雜元素的內部結構解耦。組合模式讓你可以最佳化處理遞迴或分級資料結構。有許多關於分級資料結構的例子,使得組合模式非常有用武之地。關於分級資料結構的一個普遍性的例子是你每次使用電腦時所遇到的:檔案系統。檔案系統由目錄和檔案組成。每個目錄都可以裝內容。目錄的內容可以是檔案,也可以是目錄。按照這種方式,計算機的檔案系統就是以遞迴結構來組織的。如果你想要描述這樣的資料結構,那麼你可以使用組合模式。

組合模式請看:

http://www.cnblogs.com/wxisme/p/4692637.html

小結:

  各種設計模式應該是經常組合起來用的而並不是單獨使用。只有在適合的場景下把合適的設計模式組合起來才能發揮其巨大威力。但是也要注意過度的使用設計模式可能導致程式碼被過度工程化。用該總是用最簡單的解決方案完成工作,並在真正需要的地方使用。 其他的設計模式還有:架構模式、領域特定模式、業務流程模式、使用者介面設計模式、反模式等等,並不是用到了哪個設計模式就要按照它固有的格式來用,這個要看具體的場景,靈活而準確的用好設計模式非一日之功啊,需要不斷的去積累經驗。在前進的路上。。。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30046312/viewspace-2139649/,如需轉載,請註明出處,否則將追究法律責任。

相關文章