淺談軟件開發中的設計原則及設計模式

SOLID

設計模式的六大原則有:java

Single Responsibility Principle:單一職責原則算法

Open Closed Principle:開閉原則數據庫

Liskov Substitution Principle:里氏替換原則編程

Law of Demeter:迪米特法則設計模式

Interface Segregation Principle:接口隔離原則數據結構

Dependence Inversion Principle:依賴倒置原則框架

把這六個原則的首字母聯合起來( L 算作一個)就是 SOLID (solid,穩定的),其表明的含義就是這六個原則結合使用的好處:創建穩定、靈活、健壯的設計。函數

單一職責原則

單一職責原則的英文名稱是Single Responsibility Principle,簡稱是SRP。 SRP原則的解釋是:There should never be more than one reason for a class to change。定義很簡單,即不能存在多於一個致使類變動的緣由。簡單的說就是一個類只負責一項職責。 在軟件設計中,秉承着「高內聚,低耦合」的思想,讓一個類僅負責一項職責,若是一個類有多於一項的職責,那麼就表明這個類耦合性變高了,這些職責耦合在了一塊兒,這是比較脆弱的設計。由於一旦某一項職責發生了改變,須要去更改代碼,那麼有可能會引發其餘職責改變。所謂牽一髮而動全身,這顯然是咱們所不肯意看到的,因此咱們會把這個類分拆開來,由兩個類來分別維護這兩個職責,這樣當一個職責發生改變,須要修改時,不會影響到另外一個職責。工具

固然,這個原則不只僅適用於類,對於接口和方法也適用,即一個接口/方法,只負責一件事,這樣的話,接口就會變得簡單,方法中的代碼也會更少,易讀,便於維護。學習

事實上,因爲一些其餘的因素影響,類的單一職責在項目中是很難保證的。一般,接口和方法的單一職責更容易實現。

單一原則的好處:

下降了類的複雜度。一個類只負責一項職責比負責多項職責要簡單得多。

提升了代碼的可讀性。一個類簡單了,可讀性天然就提升了。

提升了系統的可維護性。代碼的可讀性高了,而且修改一項職責對其餘職責影響下降了,可維護性天然就提升了。

變動引發的風險變低了。單一職責最大的優勢就是修改一個功能,對其餘功能的影響顯著下降。

里氏替換原則

里氏替換原則的定義以下:

Functions that use use pointers or references to base classes must be able to use objects of derived classes without knowing it.

翻譯過來就是,全部引用基類的地方必須能透明地使用其子類的對象。

里氏替換原則的意思是,全部基類在的地方,均可以換成子類,程序還能夠正常運行。這個原則是與面嚮對象語言的 繼承 特性密切相關的。

里氏替換原則包含如下4層含義:

子類能夠實現父類的抽象方法,可是不能覆蓋父類的非抽象方法。

子類中能夠增長本身特有的方法。

當子類覆蓋或實現父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬鬆。

當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更嚴格。

  子類能夠實現父類的抽象方法,可是不能覆蓋父類的非抽象方法。在咱們作系統設計時,常常會設計接口或抽象類,而後由子類來實現抽象方法,這裏使用的其實就是里氏替換原則。子類能夠實現父類的抽象方法很好理解,事實上,子類也必須徹底實現父類的抽象方法,哪怕寫一個空方法,不然會編譯報錯。里氏替換原則的關鍵點在於不能覆蓋父類的非抽象方法。父類中凡是已經實現好的方法,其實是在設定一系列的規範和契約,雖然它不強制要求全部的子類必須聽從這些規範,可是若是子類對這些非抽象方法任意修改,就會對整個繼承體系形成破壞。而里氏替換原則就是表達了這一層含義。所以,能夠看到, LSP 原則最重要的一點就是:避免子類重寫父類中已經實現的方法。這就是 LSP 原則的本質。通常來說,程序中父類大可能是抽象類,由於父類只是一個框架,具體功能還須要子類來實現。所以不多直接去 new 一個父類。而若是出現這種狀況,那麼就說明父類中實現的代碼已經很好了,子類只須要對其進行擴展就會,儘可能避免對其已經實現的方法再去重寫。

依賴倒置原則

依賴倒置原則的原始定義是這樣的:

High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.

翻譯一下:

高層模塊不該該依賴底層模塊,二者都應該依賴其抽象。

抽象不該該依賴細節。

細節應該依賴抽象。

在Java語言中的表現就是:

模塊間的依賴經過抽象發生,實現類之間不發生直接的依賴關係,其依賴關係是經過接口或抽象類產生的。 接口或抽象類不依賴於實現類。實現類依賴於接口或抽象類。每一個類儘可能都有接口或抽象類,或者抽象類和接口二者都具有 變量的表面類型儘可能是接口或者是抽象類 任何類都不該該從具體類派生 儘可能不要覆寫基類的方法 結合里氏替換原則使用 以上的規則通俗說就是:接口負責定義public屬性和方法,而且聲明與其餘對象的依賴關係,抽象類負責公共構造部分的實現,實現類準確的實現業務邏輯,同時在適當的時候對父類進行細化。

接口隔離原則

首先聲明,該原則中的接口,是一個泛泛而言的接口,不只僅指Java中的接口,還包括其中的抽象類。

首先,給出該原則的定義,該原則有兩個定義:

Clients should not be forced to depend upon interfaces that they don`t use.

客戶端不該該依賴它不須要的接口。

The dependency of one class to another one should depend on the smallest possible.

類間的依賴關係應該創建在最小的接口上。

這是什麼意思呢,這是讓咱們把接口進行細分。舉個例子,若是一個類實現一個接口,但這個接口中有它不須要的方法,那麼就須要把這個接口拆分,把它須要的方法提取出來,組成一個新的接口讓這個類去實現,這就是接口隔離原則。簡而言之,就是說,接口中的全部方法對其實現的子類都是有用的。不然,就將接口繼續細分。

看起來,該原則與單一職責原則很相像。確實很像,兩者都是強調要將接口進行細分,只不過度的方式不一樣。單一職責原則是按照 職責 進行劃分接口的;而接口隔離原則則是按照實現類對方法的使用來劃分的。能夠說,接口隔離原則更細一些。

要想完美地實現該原則,基本上就須要每一個實現類都有一個專用的接口。但實際開發中,這樣顯然是不可能的,並且,這樣很容易違背單一職責原則(可能出現同一個職責分紅了好幾個接口的狀況),所以咱們能作的就是儘可能細分。

該原則主要強調兩點:

接口要儘可能小

接口隔離原則拆分接口時,首先必需要知足單一職責原則(SRP)

接口要高內聚

高內聚就是提升接口、類、模塊的處理能力,減小對外的交互。具體就是,要求在接口中儘可能少公佈public方法,接口是對外的承諾,承諾越少對系統的開發越有利,變動的風險也就越少,同時也有利於下降成本。 到了這裏,咱們對依賴倒置原則的「依賴」就很好理解了,可是什麼是「倒置」呢。是這樣子的,剛開始按照正常人的通常思惟方式,我想吃香蕉就是吃香蕉,想吃蘋果就吃蘋果,編程也是這樣,都是按照面向實現的思惟方式來設計。而如今要倒置思惟,提取公共的抽象,面向接口(抽象類)編程。再也不依賴於具體實現了,而是依賴於接口或抽象類,這就是依賴的思惟方式「倒置」了。

與單一職責原則的區別

  到了這裏,有些人可能以爲接口隔離原則與單一職責原則很類似,其實否則。

  第一,單一職責原則注重的是職責;而接口隔離原則注重對接口依賴的隔離。

  第二,單一職責原則主要是約束類,其次纔是接口和方法,它針對的是程序中的實現和細節;而接口隔離原則主要約束接口,主要針對抽象,針對程序總體框架的構建。

注意事項

  原則是前人經驗的總結,在軟件設計中具備必定的指導做用,可是不能徹底照搬這些原則。對於接口隔離原則來講,接口儘可能小,可是也要有限度。對接口進行細化能夠提升程序設計靈活性是不爭的事實,可是若是太小,則會形成接口數量過多,使設計複雜化,因此必定要適度。

迪米特法則

迪米特法則也叫最少知識原則(Least Knowledge Principle, LKP)

雖然名稱不一樣,但都是同一個意思:一個對象應該對其餘對象有最少的瞭解。

迪米特法則要求類」羞澀」一點,儘可能不要對外公佈太多的public方法和非靜態的public變量,儘可能內斂,多使用private、package-private、protected等訪問權限。

實現:

1. 優先考慮將一個類設置成不變類
2. 儘可能下降一個類的訪問權限
3. 謹慎使用Serializable
4. 儘可能下降成員的訪問權限
複製代碼

這個原則也沒什麼須要多講的,調用者只須要知道被調用者公開的方法就行了,至於它內部是怎麼實現的或是有其餘別的方法,調用者並不關心,調用者只關心它須要用的。反而,若是被調用者暴露太多不須要暴露的屬性或方法,那麼就可能致使調用者濫用其中的方法,或是引發一些其餘沒必要要的麻煩。

開閉原則

開閉原則全部設計模式原則中,最基礎的那個原則。首先,仍是先來看一下它的定義:

Software entities like classes, modules and functions should be open for extension but closed for modifications.

翻譯過來就是:一個軟件實體,如類、模塊和函數應該對擴展開放,對修改關閉。

開閉原則以前也提到過,在 LSP 中,咱們說,要避免子類重寫父類中已經實現的方法。這個時候,繼承父類就是對其進行擴展,但沒有進行修改。這就是開閉原則一個很好的體現。

那是否是開閉原則與 LSP 原則混淆了呢?並非,LSP原則強調的是基類與子類的關係,只是其中的一種實現方式用到了開閉原則而已。開閉原則是最基礎的設計原則,其它的五個設計原則都是開閉原則的具體形態,也就是說其它的五個設計原則是指導設計的工具和方法,而開閉原則纔是其精神領袖。依照java語言的稱謂,開閉原則是抽象類,而其它的五個原則是具體的實現類。在面向對象的設計中,全部的邏輯都是從原子邏輯組合而來,不是在一個類中獨立實現一個業務邏輯。只有這樣的代碼才能夠複用,粒度越小,被複用的可能性越大。那爲何要複用呢?減小代碼的重複,避免相同的邏輯分散在多個角落,減小維護人員的工做量。那怎麼才能提升複用率呢?縮小邏輯粒度,直到一個邏輯不能夠分爲止。

如何使用開閉原則

第一:抽象約束

抽象是對一組事物的通用描述,沒有具體的實現,也就表示它能夠有很是多的可能性,能夠跟隨需求的變化而變化。所以,經過接口或抽象類能夠約束一組可能變化的行爲,而且可以實現對擴展開放,其包含三層含義: 經過接口或抽象類約束擴散,對擴展進行邊界限定,不容許出如今接口或抽象類中不存在的public方法。 參數類型,引用對象儘可能使用接口或抽象類,而不是實現類,這主要是實現里氏替換原則的一個要求 抽象層儘可能保持穩定,一旦肯定就不要修改

第二:元數據(metadata)控件模塊行爲

編程是一個很苦很累的活,那怎麼才能減輕壓力呢?答案是儘可能使用元數據來控制程序的行爲,減小重複開發。什麼是元數據?用來描述環境和數據的數據,通俗的說就是配置參數,參數能夠從文件中得到,也能夠從數據庫中得到。

第三:制定項目章程

在一個團隊中,創建項目章程是很是重要的,由於章程是全部人員都必須遵照的約定,對項目來講,約定優於配置。這比經過接口或抽象類進行約束效率更高,而擴展性一點也沒有減小。

第四:封裝變化 對變化封裝包含兩層含義: (1)將相同的變化封裝到一個接口或抽象類中 (2)將不一樣的變化封裝到不一樣的接口或抽象類中,不該該有兩個不一樣的變化出如今同一個接口或抽象類中。 封裝變化,也就是受保護的變化,找出預計有變化或不穩定的點,咱們爲這些變化點建立穩定的接口。

總結

總而言之,這六個設計原則是之後學習設計模式的基礎,它們的共同目的就是SOLID——創建穩定、靈活、健壯的設計。可是原則歸原則,有時候因爲種種緣由,這些條條框框是不得不去打破的,一味地遵循它是不會有好果子吃的(就像接口隔離原則,不可能建立那麼多的接口)。所以咱們應該正確使用這些原則,主要目的仍是爲了咱們軟件的穩定性、靈活性、健壯性和可維護性。

JAVA設計模式總結

1、什麼是設計模式

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

2、設計模式的三個分類

建立型模式:對象實例化的模式,建立型模式用於解耦對象的實例化過程。

結構型模式:把類或對象結合在一塊兒造成一個更大的結構。

行爲型模式:類和對象如何交互,及劃分責任和算法。

建立型有:

1、Singleton,單例模式:保證一個類只有一個實例,並提供一個訪問它的全局訪問點

2、Abstract Factory,抽象工廠:提供一個建立一系列相關或相互依賴對象的接口,而無須指定它們的具體類。 3、Factory Method,工廠方法:定義一個用於建立對象的接口,讓子類決定實例化哪個類,Factory Method使一個類的實例化延遲到了子類。

4、Builder,建造模式:將一個複雜對象的構建與他的表示相分離,使得一樣的構建過程能夠建立不一樣的表示。

5、Prototype,原型模式:用原型實例指定建立對象的種類,而且經過拷貝這些原型來建立新的對象。

行爲型有:

6、Iterator,迭代器模式:提供一個方法順序訪問一個聚合對象的各個元素,而又不須要暴露該對象的內部表示。

7、Observer,觀察者模式:定義對象間一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知自動更新。

8、Template Method,模板方法:定義一個操做中的算法的骨架,而將一些步驟延遲到子類中,TemplateMethod使得子類能夠不改變一個算法的結構便可以重定義該算法得某些特定步驟。

9、Command,命令模式:將一個請求封裝爲一個對象,從而使你能夠用不一樣的請求對客戶進行參數化,對請求排隊和記錄請求日誌,以及支持可撤銷的操做。

10、State,狀態模式:容許對象在其內部狀態改變時改變他的行爲。對象看起來彷佛改變了他的類。

11、Strategy,策略模式:定義一系列的算法,把他們一個個封裝起來,並使他們能夠互相替換,本模式使得算法能夠獨立於使用它們的客戶。

12、China of Responsibility,職責鏈模式:使多個對象都有機會處理請求,從而避免請求的送發者和接收者之間的耦合關係

十3、Mediator,中介者模式:用一箇中介對象封裝一些列的對象交互。

十4、Visitor,訪問者模式:表示一個做用於某對象結構中的各元素的操做,它使你能夠在不改變各元素類的前提下定義做用於這個元素的新操做。

十5、Interpreter,解釋器模式:給定一個語言,定義他的文法的一個表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。

十6、Memento,備忘錄模式:在不破壞對象的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。

結構型有:

十7、Composite,組合模式:將對象組合成樹形結構以表示部分總體的關係,Composite使得用戶對單個對象和組合對象的使用具備一致性。

十8、Facade,外觀模式:爲子系統中的一組接口提供一致的界面,facade提供了一高層接口,這個接口使得子系統更容易使用。

十9、Proxy,代理模式:爲其餘對象提供一種代理以控制對這個對象的訪問

二10、Adapter,適配器模式:將一類的接口轉換成客戶但願的另一個接口,Adapter模式使得本來因爲接口不兼容而不能一塊兒工做那些類能夠一塊兒工做。

二11、Decrator,裝飾模式:動態地給一個對象增長一些額外的職責,就增長的功能來講,Decorator模式相比生成子類更加靈活。

二12、Bridge,橋接模式:將抽象部分與它的實現部分相分離,使他們能夠獨立的變化。

二十3、Flyweight,享元模式:運用共享技術有效地支持大量細粒度的對象。

3、淺談23種設計模式

1.單例模式
單例模式,它的定義就是確保某一個類只有一個實例,而且提供一個全局訪問點。 單例模式具有典型的3個特色: 一、只有一個實例。

二、自我實例化。

三、提供全局訪問點。

所以當系統中只須要一個實例對象或者系統中只容許一個公共訪問點,除了這個公共訪問點外,不能經過其餘訪問點訪問該實例時,能夠使用單例模式。 單例模式的主要優勢就是節約系統資源、提升了系統效率,同時也可以嚴格控制客戶對它的訪問。也許就是由於系統中只有一個實例,這樣就致使了單例類的職責太重,違背了「單一職責原則」,同時也沒有抽象類,因此擴展起來有必定的困難。

2.工廠方法模式
做爲抽象工廠模式的孿生兄弟,工廠方法模式定義了一個建立對象的接口,但由子類決定要實例化的類是哪個,也就是說工廠方法模式讓實例化推遲到子類。工廠方法模式很是符合「開閉原則」,當須要增長一個新的產品時,咱們只須要增長一個具體的產品類和與之對應的具體工廠便可,無須修改原有系統。同時在工廠方法模式中用戶只須要知道生產產品的具體工廠便可,無須關係產品的建立過程,甚至連具體的產品類名稱都不須要知道。雖然他很好的符合了「開閉原則」,可是因爲每新增一個新產品時就須要增長兩個類,這樣勢必會致使系統的複雜度增長。

3.抽象工廠模式
所謂抽象工廠模式就是提供一個接口,用於建立相關或者依賴對象的家族,而不須要明確指定具體類。他容許客戶端使用抽象的接口來建立一組相關的產品,而不須要關係實際產出的具體產品是什麼。這樣一來,客戶就能夠從具體的產品中被解耦。它的優勢是隔離了具體類的生成,使得客戶端不須要知道什麼被建立了,而缺點就在於新增新的行爲會比較麻煩,由於當添加一個新的產品對象時,須要更加須要更改接口及其下全部子類。

4.建造者模式
對於建造者模式而已,它主要是將一個複雜對象的構建與表示分離,使得一樣的構建過程能夠建立不一樣的表示。適用於那些產品對象的內部結構比較複雜。建造者模式將複雜產品的構建過程封裝分解在不一樣的方法中,使得建立過程很是清晰,可以讓咱們更加精確的控制複雜產品對象的建立過程,同時它隔離了複雜產品對象的建立和使用,使得相同的建立過程可以建立不一樣的產品。可是若是某個產品的內部結構過於複雜,將會致使整個系統變得很是龐大,不利於控制,同時若幾個產品之間存在較大的差別,則不適用建造者模式,畢竟這個世界上存在相同點大的兩個產品並非不少,因此它的使用範圍有限。

5.原型模式
在咱們應用程序可能有某些對象的結構比較複雜,可是咱們又須要頻繁的使用它們,若是這個時候咱們來不斷的新建這個對象勢必會大大損耗系統內存的,這個時候咱們須要使用原型模式來對這個結構複雜又要頻繁使用的對象進行克隆。因此原型模式就是用原型實例指定建立對象的種類,而且經過複製這些原型建立新的對象。它主要應用與那些建立新對象的成本過大時。它的主要優勢就是簡化了新對象的建立過程,提升了效率,同時原型模式提供了簡化的建立結構。

模式結構 原型模式包含以下角色: Prototype:抽象原型類 ConcretePrototype:具體原型類 Client:客戶類

6.適配器模式
在咱們的應用程序中咱們可能須要將兩個不一樣接口的類來進行通訊,在不修改這兩個的前提下咱們可能會須要某個中間件來完成這個銜接的過程。這個中間件就是適配器。所謂適配器模式就是將一個類的接口,轉換成客戶指望的另外一個接口。它可讓本來兩個不兼容的接口可以無縫完成對接。做爲中間件的適配器將目標類和適配者解耦,增長了類的透明性和可複用性。

適配器模式包含以下角色:

Target:目標抽象類

Adapter:適配器類

Adaptee:適配者類

Client:客戶類

7.橋接模式
若是說某個系統可以從多個角度來進行分類,且每一種分類均可能會變化,那麼咱們須要作的就是講這多個角度分離出來,使得他們能獨立變化,減小他們之間的耦合,這個分離過程就使用了橋接模式。所謂橋接模式就是講抽象部分和實現部分隔離開來,使得他們可以獨立變化。橋接模式將繼承關係轉化成關聯關係,封裝了變化,完成了解耦,減小了系統中類的數量,也減小了代碼量。

橋接模式包含以下角色:

Abstraction:抽象類

RefinedAbstraction:擴充抽象類

Implementor:實現類接口

ConcreteImplementor:具體實現類

8.組合模式
組合模式組合多個對象造成樹形結構以表示「總體-部分」的結構層次。它定義瞭如何將容器對象和葉子對象進行遞歸組合,使得客戶在使用的過程當中無須進行區分,能夠對他們進行一致的處理。在使用組合模式中須要注意一點也是組合模式最關鍵的地方:葉子對象和組合對象實現相同的接口。這就是組合模式可以將葉子節點和對象節點進行一致處理的緣由。雖然組合模式可以清晰地定義分層次的複雜對象,也使得增長新構件也更容易,可是這樣就致使了系統的設計變得更加抽象,若是系統的業務規則比較複雜的話,使用組合模式就有必定的挑戰了。

模式結構 組合模式包含以下角色:

Component: 抽象構件

Leaf: 葉子構件

Composite: 容器構件

Client: 客戶類

9.裝飾模式
咱們能夠經過繼承和組合的方式來給一個對象添加行爲,雖然使用繼承可以很好擁有父類的行爲,可是它存在幾個缺陷:1、對象之間的關係複雜的話,系統變得複雜不利於維護。2、容易產生「類爆炸」現象。3、是靜態的。在這裏咱們能夠經過使用裝飾者模式來解決這個問題。裝飾者模式,動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更加有彈性的替代方案。雖然裝飾者模式可以動態將責任附加到對象上,可是他會產生許多的細小對象,增長了系統的複雜度。

模式結構 裝飾模式包含以下角色:

Component: 抽象構件

ConcreteComponent: 具體構件

Decorator: 抽象裝飾類

ConcreteDecorator: 具體裝飾類

10.外觀模式
咱們都知道類與類之間的耦合越低,那麼可複用性就越好,若是兩個類沒必要彼此通訊,那麼就不要讓這兩個類發生直接的相互關係,若是須要調用裏面的方法,能夠經過第三者來轉發調用。外觀模式很是好的詮釋了這段話。外觀模式提供了一個統一的接口,用來訪問子系統中的一羣接口。它讓一個應用程序中子系統間的相互依賴關係減小到了最少,它給子系統提供了一個簡單、單一的屏障,客戶經過這個屏障來與子系統進行通訊。經過使用外觀模式,使得客戶對子系統的引用變得簡單了,實現了客戶與子系統之間的鬆耦合。可是它違背了「開閉原則」,由於增長新的子系統可能須要修改外觀類或客戶端的源代碼。

外觀模式包含以下角色:

Facade: 外觀角色

SubSystem:子系統角色

11.亨元模式
在一個系統中對象會使得內存佔用過多,特別是那些大量重複的對象,這就是對系統資源的極大浪費。享元模式對對象的重用提供了一種解決方案,它使用共享技術對相同或者類似對象實現重用。享元模式就是運行共享技術有效地支持大量細粒度對象的複用。系統使用少許對象,並且這些都比較類似,狀態變化小,能夠實現對象的屢次複用。這裏有一點要注意:享元模式要求可以共享的對象必須是細粒度對象。享元模式經過共享技術使得系統中的對象個數大大減小了,同時享元模式使用了內部狀態和外部狀態,同時外部狀態相對獨立,不會影響到內部狀態,因此享元模式可以使得享元對象在不一樣的環境下被共享。同時正是分爲了內部狀態和外部狀態,享元模式會使得系統變得更加複雜,同時也會致使讀取外部狀態所消耗的時間過長。

享元模式包含以下角色:

Flyweight: 抽象享元類

ConcreteFlyweight: 具體享元類

UnsharedConcreteFlyweight: 非共享具體享元類

FlyweightFactory: 享元工廠類

12.代理模式
代理模式就是給一個對象提供一個代理,並由代理對象控制對原對象的引用。它使得客戶不能直接與真正的目標對象通訊。代理對象是目標對象的表明,其餘須要與這個目標對象打交道的操做都是和這個代理對象在交涉。代理對象能夠在客戶端和目標對象之間起到中介的做用,這樣起到了的做用和保護了目標對象的,同時也在必定程度上面減小了系統的耦合度。

代理模式包含以下角色:

 Subject: 抽象主題角色

 Proxy: 代理主題角色

 RealSubject: 真實主題角色

13.訪問者模式
訪問者模式俗稱23大設計模式中最難的一個。除告終構複雜外,理解也比較難。在咱們軟件開發中咱們可能會對同一個對象有不一樣的處理,若是咱們都作分別的處理,將會產生災難性的錯誤。對於這種問題,訪問者模式提供了比較好的解決方案。訪問者模式即表示一個做用於某對象結構中的各元素的操做,它使咱們能夠在不改變各元素的類的前提下定義做用於這些元素的新操做。 訪問者模式的目的是封裝一些施加於某種數據結構元素之上的操做,一旦這些操做須要修改的話,接受這個操做的數據結構能夠保持不變。爲不一樣類型的元素提供多種訪問操做方式,且能夠在不修改原有系統的狀況下增長新的操做方式。同時咱們還須要明確一點那就是訪問者模式是適用於那些數據結構比較穩定的,由於他是將數據的操做與數據結構進行分離了,若是某個系統的數據結構相對穩定,可是操做算法易於變化的話,就比較適用適用訪問者模式,由於訪問者模式使得算法操做的增長變得比較簡單了。

訪問者模式包含以下角色:

Vistor: 抽象訪問者

ConcreteVisitor: 具體訪問者

Element: 抽象元素

ConcreteElement: 具體元素

ObjectStructure: 對象結構

14.模板模式
有些時候咱們作某幾件事情的步驟都差很少,僅有那麼一小點的不一樣,在軟件開發的世界裏一樣如此,若是咱們都將這些步驟都一一作的話,費時費力不討好。因此咱們能夠將這些步驟分解、封裝起來,而後利用繼承的方式來繼承便可,固然不一樣的能夠本身重寫實現嘛!這就是模板方法模式提供的解決方案。 所謂模板方法模式就是在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類能夠在不改變算法結構的狀況下,從新定義算法中的某些步驟。 模板方法模式就是基於繼承的代碼複用技術的。在模板方法模式中,咱們能夠將相同部分的代碼放在父類中,而將不一樣的代碼放入不一樣的子類中。也就是說咱們須要聲明一個抽象的父類,將部分邏輯以具體方法以及具體構造函數的形式實現,而後聲明一些抽象方法讓子類來實現剩餘的邏輯,不一樣的子類能夠以不一樣的方式來實現這些邏輯。因此模板方法的模板其實就是一個普通的方法,只不過這個方法是將算法實現的步驟封裝起來的。

模板方法模式包含以下角色:

AbstractClass: 抽象類

ConcreteClass: 具體子類

15.策略模式 咱們知道一件事可能會有不少種方式來實現它,可是其中總有一種最高效的方式,在軟件開發的世界裏面一樣如此,咱們也有不少中方法來實現一個功能,可是咱們須要一種簡單、高效的方式來實現它,使得系統可以很是靈活,這就是策略模式。 因此策略模式就是定義了算法族,分別封裝起來,讓他們以前能夠互相轉換,此模式然該算法的變化獨立於使用算法的客戶。 在策略模式中它將這些解決問題的方法定義成一個算法羣,每個方法都對應着一個具體的算法,這裏的一個算法我就稱之爲一個策略。雖然策略模式定義了算法,可是它並不提供算法的選擇,即什麼算法對於什麼問題最合適這是策略模式所不關心的,因此對於策略的選擇仍是要客戶端來作。客戶必需要清楚的知道每一個算法之間的區別和在何時什麼地方使用什麼策略是最合適的,這樣就增長客戶端的負擔。 同時策略模式也很是完美的符合了「開閉原則」,用戶能夠在不修改原有系統的基礎上選擇算法或行爲,也能夠靈活地增長新的算法或行爲。可是一個策略對應一個類將會是系統產生不少的策略類。

策略模式包含以下角色:

Context: 環境類

Strategy: 抽象策略類

ConcreteStrategy: 具體策略類

16.狀態模式
在不少狀況下咱們對象的行爲依賴於它的一個或者多個變化的屬性,這些可變的屬性咱們稱之爲狀態,也就是說行爲依賴狀態,即當該對象由於在外部的互動而致使他的狀態發生變化,從而它的行爲也會作出相應的變化。對於這種狀況,咱們是不能用行爲來控制狀態的變化,而應該站在狀態的角度來思考行爲,便是什麼狀態就要作出什麼樣的行爲。這個就是狀態模式。 因此狀態模式就是容許對象在內部狀態發生改變時改變它的行爲,對象看起來好像修改了它的類。在狀態模式中咱們能夠減小大塊的if…else語句,它是容許態轉換邏輯與狀態對象合成一體,可是減小if…else語句的代價就是會換來大量的類,因此狀態模式勢必會增長系統中類或者對象的個數。同時狀態模式是將全部與某個狀態有關的行爲放到一個類中,而且能夠方便地增長新的狀態,只須要改變對象狀態便可改變對象的行爲。可是這樣就會致使系統的結構和實現都會比較複雜,若是使用不當就會致使程序的結構和代碼混亂,不利於維護。

狀態模式包含以下角色:

Context: 環境類

State: 抽象狀態類

ConcreteState: 具體狀態類

17.觀察者模式
何謂觀察者模式?觀察者模式定義了對象之間的一對多依賴關係,這樣一來,當一個對象改變狀態時,它的全部依賴者都會收到通知而且自動更新。在這裏,發生改變的對象稱之爲觀察目標,而被通知的對象稱之爲觀察者。一個觀察目標能夠對應多個觀察者,並且這些觀察者之間沒有相互聯繫,因此麼能夠根據須要增長和刪除觀察者,使得系統更易於擴展。因此觀察者提供了一種對象設計,讓主題和觀察者之間以鬆耦合的方式結合。

觀察者模式包含以下角色:

Subject: 目標

ConcreteSubject: 具體目標

Observer: 觀察者

ConcreteObserver: 具體觀察者

18.備忘錄模式
後悔藥人人都想要,可是事實倒是殘酷的,根本就沒有後悔藥可買,可是也不只如此,在軟件的世界裏就有後悔藥!備忘錄模式就是一種後悔藥,它給咱們的軟件提供後悔藥的機制,經過它能夠使系統恢復到某一特定的歷史狀態。 所謂備忘錄模式就是在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態,這樣能夠在之後將對象恢復到原先保存的狀態。它實現了對信息的封裝,使得客戶不須要關心狀態保存的細節。保存就要消耗資源,因此備忘錄模式的缺點就在於消耗資源。若是類的成員變量過多,勢必會佔用比較大的資源,並且每一次保存都會消耗必定的內存。

備忘錄模式包含以下角色:

Originator: 原發器

Memento: 備忘錄

Caretaker: 負責人

19.中介者模式

租房各位都有過的經歷吧!在這個過程當中中介結構扮演着很重要的角色,它在這裏起到一箇中間者的做用,給咱們和房主互相傳遞信息。在外面軟件的世界裏一樣須要這樣一箇中間者。在咱們的系統中有時候會存在着對象與對象之間存在着很強、複雜的關聯關係,若是讓他們之間有直接的聯繫的話,一定會致使整個系統變得很是複雜,並且可擴展性不好!在前面咱們就知道若是兩個類之間沒有沒必要彼此通訊,咱們就不該該讓他們有直接的關聯關係,若是實在是須要通訊的話,咱們能夠經過第三者來轉發他們的請求。一樣,這裏咱們利用中介者來解決這個問題。 所謂中介者模式就是用一箇中介對象來封裝一系列的對象交互,中介者使各對象不須要顯式地相互引用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互。在中介者模式中,中介對象用來封裝對象之間的關係,各個對象能夠不須要知道具體的信息經過中介者對象就能夠實現相互通訊。它減小了對象之間的互相關係,提供了系統可複用性,簡化了系統的結構。 在中介者模式中,各個對象不須要互相知道了解,他們只須要知道中介者對象便可,可是中介者對象就必需要知道全部的對象和他們之間的關聯關係,正是由於這樣就致使了中介者對象的結構過於複雜,承擔了過多的職責,同時它也是整個系統的核心所在,它有問題將會致使整個系統的問題。因此若是在系統的設計過程當中若是出現「多對多」的複雜關係羣時,千萬別急着使用中介者模式,而是要仔細思考是否是您設計的系統存在問題。

Mediator: 抽象中介者

ConcreteMediator: 具體中介者

Colleague: 抽象同事類

ConcreteColleague: 具體同事類

20.迭代器模式
對於迭代在編程過程當中咱們常常用到,可以遊走於聚合內的每個元素,同時還能夠提供多種不一樣的遍歷方式,這就是迭代器模式的設計動機。在咱們實際的開發過程當中,咱們可能會須要根據不一樣的需求以不一樣的方式來遍歷整個對象,可是咱們又不但願在聚合對象的抽象接口中充斥着各類不一樣的遍歷操做,因而咱們就但願有某個東西可以以多種不一樣的方式來遍歷一個聚合對象,這時迭代器模式出現了。

何爲迭代器模式?所謂迭代器模式就是提供一種方法順序訪問一個聚合對象中的各個元素,而不是暴露其內部的表示。迭代器模式是將迭代元素的責任交給迭代器,而不是聚合對象,咱們甚至在不須要知道該聚合對象的內部結構就能夠實現該聚合對象的迭代。

經過迭代器模式,使得聚合對象的結構更加簡單,它不須要關注它元素的遍歷,只須要專一它應該專一的事情,這樣就更加符合單一職責原則了。

迭代器模式包含以下角色:

Iterator: 抽象迭代器

ConcreteIterator: 具體迭代器

Aggregate: 抽象聚合類

ConcreteAggregate: 具體聚合類

21.解釋器模式
所謂解釋器模式就是定義語言的文法,而且創建一個解釋器來解釋該語言中的句子。解釋器模式描述瞭如何構成一個簡單的語言解釋器,主要應用在使用面嚮對象語言開發的編譯器中。它描述瞭如何爲簡單的語言定義一個文法,如何在該語言中表示一個句子,以及如何解釋這些句子。

解釋器模式包含以下角色:

AbstractExpression: 抽象表達式

TerminalExpression: 終結符表達式

NonterminalExpression: 非終結符表達式

Context: 環境類 Client: 客戶類

22.命令模式
有些時候咱們想某個對象發送一個請求,可是咱們並不知道該請求的具體接收者是誰,具體的處理過程是如何的,們只知道在程序運行中指定具體的請求接收者便可,對於這樣將請求封裝成對象的咱們稱之爲命令模式。因此命令模式將請求封裝成對象,以便使用不一樣的請求、隊列或者日誌來參數化其餘對象。同時命令模式支持可撤銷的操做。

命令模式能夠將請求的發送者和接收者之間實現徹底的解耦,發送者和接收者之間沒有直接的聯繫,發送者只須要知道如何發送請求命令便可,其他的能夠一律無論,甚至命令是否成功都無需關心。同時咱們能夠很是方便的增長新的命令,可是可能就是由於方便和對請求的封裝就會致使系統中會存在過多的具體命令類。

命令模式包含以下角色:

Command: 抽象命令類

ConcreteCommand: 具體命令類

Invoker: 調用者

Receiver: 接收者

Client:客戶類

23.責任鏈模式
職責鏈模式描述的請求如何沿着對象所組成的鏈來傳遞的。它將對象組成一條鏈,發送者將請求發給鏈的第一個接收者,而且沿着這條鏈傳遞,直到有一個對象來處理它或者直到最後也沒有對象處理而留在鏈末尾端。

避免請求發送者與接收者耦合在一塊兒,讓多個對象都有可能接收請求,將這些對象鏈接成一條鏈,而且沿着這條鏈傳遞請求,直到有對象處理它爲止,這就是職責鏈模式。在職責鏈模式中,使得每個對象都有可能來處理請求,從而實現了請求的發送者和接收者之間的解耦。同時職責鏈模式簡化了對象的結構,它使得每一個對象都只須要引用它的後繼者便可,而沒必要了解整條鏈,這樣既提升了系統的靈活性也使得增長新的請求處理類也比較方便。可是在職責鏈中咱們不能保證全部的請求都可以被處理,並且不利於觀察運行時特徵。

職責鏈模式包含以下角色:

Handler: 抽象處理者

ConcreteHandler: 具體處理者

Client: 客戶類

相關文章
相關標籤/搜索