重溫設計模式

  設計模式,及軟件設計中的「套路」。每個模式描述了一個在咱們周圍不斷重複發生的問題,以及該問題解決方案的核心,這樣,你就能一次又一次的使用該方案而沒必要作重複的勞動。設計模式大約有20多種,它們令人們能夠更加簡單方便的複用成功的設計和體系結構,提升系統維護的有效性。與設計模式密切相關的是6大設計原則,那麼就從這些設計原則開始設計模式重溫之旅吧。(ps:內容有點小多)java

1、6大設計模式

一、單一職責原則

  • 核心思想:應該有且僅有一個緣由引發類的變動
  • 問題描述:假若有類Class1完成職責T1,T2,當職責T1或T2有變動須要修改時,有可能影響到該類的另一個職責正常工做。
  • 好處:類的複雜度下降、可讀性提升、可維護性提升、擴展性提升、下降了變動引發的風險。
  • 需注意: 單一職責原則提出了一個編寫程序的標準,用「職責」或「變化緣由」來衡量接口或類設計得是否優良,可是「職責」和「變化緣由」都是不能夠度量的,因項目和環境而異。

  單一職責就是讓類(或方法)的功能單一,作到術業有且專攻,是否是有點UNIX設計思想的感受?git

 二、里斯替換原則

  • 核心思想:在使用基類的的地方能夠任意使用其子類,能保證子類完美替換基類。
  • 通俗來說:只要父類能出現的地方子類就能出現。反之,父類則未必能勝任。
  • 好處:加強程序的健壯性,即便增長了子類,原有的子類還能夠繼續運行。
  • 需注意:若是子類不能完整地實現父類的方法,或者父類的某些方法在子類中已經發生「畸變」,則建議斷開父子繼承關係 採用依賴、聚合、組合等關係代替繼承。

三、依賴倒置原則

  • 核心思想:高層模塊不該該依賴底層模塊,兩者都該依賴其抽象;抽象不該該依賴細節;細節應該依賴抽象;
  • 說明:高層模塊就是調用端,低層模塊就是具體實現類。抽象就是指接口或抽象類。細節就是實現類。
  • 通俗來說:依賴倒置原則的本質就是經過抽象(接口或抽象類)使個各種或模塊的實現彼此獨立,互不影響,實現模塊間的鬆耦合。
  • 問題描述:類A直接依賴類B,假如要將類A改成依賴類C,則必須經過修改類A的代碼來達成。這種場景下,類A通常是高層模塊,負責複雜的業務邏輯;類B和類C是低層模塊,負責基本的原子操做;假如修改類A,會給程序帶來沒必要要的風險。
  • 解決方案:將類A修改成依賴接口interface,類B和類C各自實現接口interface,類A經過接口interface間接與類B或者類C發生聯繫,則會大大下降修改類A的概率。
  • 好處:依賴倒置的好處在小型項目中很難體現出來。但在大中型項目中能夠減小需求變化引發的工做量。使並行開發更友好。

四、接口隔離原則

  • 核心思想:類間的依賴關係應該創建在最小的接口上
  • 通俗來說:創建單一接口,不要創建龐大臃腫的接口,儘可能細化接口,接口中的方法儘可能少。也就是說,咱們要爲各個類創建專用的接口,而不要試圖去創建一個很龐大的接口供全部依賴它的類去調用。
  • 問題描述:類A經過接口interface依賴類B,類C經過接口interface依賴類D,若是接口interface對於類A和類B來講不是最小接口,則類B和類D必須去實現他們不須要的方法。
  • 需注意:
    • 接口儘可能小,可是要有限度。對接口進行細化能夠提升程序設計靈活性,可是若是太小,則會形成接口數量過多,使設計複雜化。因此必定要適度
    • 提升內聚,減小對外交互。使接口用最少的方法去完成最多的事情
    • 爲依賴接口的類定製服務。只暴露給調用的類它須要的方法,它不須要的方法則隱藏起來。只有專一地爲一個模塊提供定製服務,才能創建最小的依賴關係。

五、迪米特原則

  • 核心思想:類間解耦。
  • 通俗來說: 一個類對本身依賴的類知道的越少越好。自從咱們接觸編程開始,就知道了軟件編程的總的原則:低耦合,高內聚。不管是面向過程編程仍是面向對象編程,只有使各個模塊之間的耦合儘可能的低,才能提升代碼的複用率。低耦合的優勢不言而喻,可是怎麼樣編程才能作到低耦合呢?那正是迪米特法則要去完成的。

六、開閉原則

  • 核心思想:儘可能經過擴展軟件實體來解決需求變化,而不是經過修改已有的代碼來完成變化
  • 通俗來說: 一個軟件產品在生命週期內,都會發生變化,既然變化是一個既定的事實,咱們就應該在設計的時候儘可能適應這些變化,以提升項目的穩定性和靈活性。

設計原則歸納

  單一職責原則告訴咱們實現類要職責單一;里氏替換原則告訴咱們不要破壞繼承體系;依賴倒置原則告訴咱們要面向接口編程;接口隔離原則告訴咱們在設計接口的時候要精簡單一;迪米特法則告訴咱們要下降耦合。而開閉原則是總綱,他告訴咱們要對擴展開放,對修改關閉。github

 

2、23種設計模式

------------------------------建立型模式------------------------------

一、單例模式

  單例模式確保一個類只有一個實例,自行初始化並向整個系統提供這個實例。一個類只有一個實例減小了內存開支,特別是一個對象頻繁建立銷燬時。單例模式可細分爲2種模式,餓漢式和懶漢式,兩者的區別是初始化實例的時間不一樣,前者是在定義時就初始化,後者是在第一次使用時初始化,這裏注意多線程的併發訪問。算法

>>單例模式示例代碼<<編程

二、工廠方法模式

  工廠方法(Factory Method)模式的意義是定義一個建立產品對象的工廠接口,將實際建立工做推遲到子類當中。核心工廠類再也不負責產品的建立,這樣核心類成爲一個抽象工廠角色,僅負責具體工廠子類必須實現的接口,這樣進一步抽象化的好處是使得工廠方法模式可使系統在不修改具體工廠角色的狀況下引進新的產品。設計模式

>>工廠方法示例代碼<<數據結構

三、抽象工廠模式

  爲建立一組相關或相互依賴的對象提供一個接口,並且無須指定它們的具體類,能夠理解爲工廠方法的升級版。多線程

>>抽象工廠示例代碼<<併發

四、建造者模式

  建造者模式也叫做生成器模式,將一個複雜對象的構建和它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。好比一個User類的屬性有name、age、address、email、job...等,若是想建立一個User對象,傳入所有的屬性有點太長了,這時可使用建造者模式,傳入一個參數就只設置對應屬性的值。框架

>>建造者模式示例代碼<<

五、原型模式

  原型模式的定義爲:用原型實例指定建立對象的種類,而且經過拷貝這些原型建立新的對象。原型模式的核心是一個clone()方法,經過該方法進行對象的複製,Java提供了一個Cloneable來標示這個對象是可拷貝的,爲何說是「標示」呢?這個接口只是一個標記做用,在JVM中具備這個標記的對象纔有可能被拷貝。那怎麼才能從「有可能被拷貝」到「能夠被拷貝」呢?方式就是覆蓋clone()方法

>>原型模式<<

 

------------------------------結構型模式------------------------------

六、適配器模式

  適配器模式定義:將一個類的接口變換爲客戶端所期待的另外一種接口,從而使本來因接口不匹配而沒法在一塊兒工做的兩個類可以在一塊兒工做。

適配器模式的注意事項

  適配器模式最好在詳細設計階段不要考慮它, 它不是爲了解決還處在開發階段的問題,而是解決正在服役的項目問題,沒有一個系統分析師會在作詳細設計的時候考慮使用適配器模式,這個模式使用的主要場景是擴展應用中,就像咱們上面的那個例子同樣,系統擴展了,不符合原有設計的時候才考慮經過適配器模式減小代碼修改帶來的風險。

>>適配器模式示例代碼<<

七、裝飾模式

  動態地給一個對象添加額外的職責,就增長功能來講,裝飾模式相比於生成子類更加靈活。裝飾模式至關於在一個構建類外層添加了一個包裹類。

>>裝飾模式示例代碼<<

八、代理模式

  代理模式是一種使用率很是高的模式,爲其餘對象提供一種代理以控制對這個對象的訪問。

  在Java中有一種動態代理技術,動態代理指實現階段不用關心代理誰,而在運行階段才指定代理哪個對象。

>>代理模式示例代碼<<

九、組合模式

  組合模式將對象組合成樹形結構以表示「總體-部分」的層次結構,使得用戶對單個對象和組合對象的使用具備一致性。

  • Component抽象構件角色:定義參加組合對象的共有方法和屬性, 能夠定義一些默認的行爲或屬性, 好比咱們例子中的getInfo就封裝到了抽象類中。
  • Leaf葉子構件:葉子對象, 其下再也沒有其餘的分支, 也就是遍歷的最小單位。
  • Composite樹枝構件:樹枝對象, 它的做用是組合樹枝節點和葉子節點造成一個樹形結構。

>>組合模式示例代碼<<

十、門面模式

  門面模式要求一個子系統的外部與其內部的通訊必須經過一個統一的對象進行。門面模式提供一個高層次的接口,使得子系統更易於使用。

  • Facade門面角色:客戶端能夠調用這個角色的方法。 此角色知曉子系統的全部功能和責任。 通常狀況下,本角色會將全部從客戶端發來的請求委派到相應的子系統去, 也就說該角色沒有實際的業務邏輯, 只是一個委託類。
  • subsystem子系統角色:能夠同時有一個或者多個子系統。 每個子系統都不是一個單獨的類, 而是一個類的集合。 子系統並不知道門面的存在。 對於子系統而言, 門面僅僅是另一個客戶端而已。

>>門面模式示例代碼<<

十一、享元模式

  享元模式是池技術的重要實現,使用共享對象可有效地支持大量的細粒度的對象。

>>享元模式示例代碼<<

十二、橋接模式

  橋樑模式定義:將抽象和實現解耦,使得二者能夠獨立的變化。

  • Abstraction——抽象化角色:它的主要職責是定義出該角色的行爲, 同時保存一個對實現化角色的引用, 該角色通常是抽象類。
  • Implementor——實現化角色:它是接口或者抽象類, 定義角色必需的行爲和屬性。
  • RefinedAbstraction——修正抽象化角色:它引用實現化角色對抽象化角色進行修正。
  • ConcreteImplementor——具體實現化角色:它實現接口或抽象類定義的方法和屬性。

>>橋接模式示例代碼<<

 

------------------------------行爲模式------------------------------

1三、責任鏈模式

  責任鏈模式定義:使多個對象都有機會處理請求,從而避免了請求的發送者和接收者之間的耦合關係。將這些對象組成一條鏈,並沿着這條鏈來傳遞請求,直到有對象處理它爲止。

>>責任鏈模式示例代碼<<

1四、迭代器模式

  迭代器模式提供了一種方法訪問一個容器對象中各個元素,而又不暴露該對象的內部細節(目前已不多用到了,容器通常都提供了迭代器)。

>>迭代器模式示例代碼<<

1五、中介者模式

  用一箇中介對象封裝一系列的對象交互,中介者使各對象不須要顯示地互相做用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互。

終結者模式的優勢:減小類間的依賴,把原來的一對多的依賴變成了一對一的依賴,同事類只依賴中介者,較少了依賴,下降了類間的耦合。

終結者模式的缺點:終結者會膨脹的很大,並且邏輯很複雜,原來N個對象直接的相互依賴關係轉換爲中介者和同事類的依賴關係,同事類越多,中介者的邏輯越複雜。

>>中介者模式設計模式<<

1六、模板方法

  定義一個操做中算法的框架,而將一些步驟延遲到子類中。使得子類能夠不改變一個算法便可重定義該算法的某些特定步驟。

基本方法:也叫做基本操做,是由子類實現的方法,而且在模板方法被調用

模板方法:能夠有一個或幾個, 通常是一個具體方法, 也就是一個框架, 實現對基本方法的調度,完成固定的邏輯。通常將模板方法加上final關鍵字,不容許被覆寫

>>模板方法示例代碼<<

1七、狀態模式

  狀態模式定義:當一個對象內在狀態改變時容許其改變行爲,這個對象看起來像改變了其類。狀態模式的核心是封裝,狀態的變動引發了行爲的變動,從外部看起來就好像這個對象對應的類發生了改變同樣。 

● State——抽象狀態角色

  接口或抽象類, 負責對象狀態定義, 而且封裝環境角色以實現狀態切換。

● ConcreteState——具體狀態角色

  每個具體狀態必須完成兩個職責:本狀態的行爲管理以及趨向狀態處理,通俗地說,就是本狀態下要作的事情, 以及本狀態如何過渡到其餘狀態。

● Context——環境角色

  定義客戶端須要的接口, 而且負責具體狀態的切換。

>>狀態模式示例代碼<<

1八、策略模式

  策略模式是比較簡單的模式,定義一組算法,將每一個算法封裝起來,而且使它們之間能夠互換。

>>策略模式示例代碼<<

1九、備忘錄模式

  備忘錄模式定義:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。這樣之後就可將該對象恢復到原先保存的狀態。

>>備忘錄模式示例代碼<<

20、觀察者模式

  觀察者模式(Observer Pattern)也叫做發佈訂閱模式,其定義以下:定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則全部依賴於它的對象都會獲得通知並自動更新。

>>觀察者模式示例代碼<<

2一、訪問者模式

  封裝一些做用於某種數據結構中的個元素的操做,它能夠在不改變數據結構的前提下定義做用於這些元素的新的操做。

>>訪問者模式示例代碼<<

2二、命令模式

  命令模式是一個高內聚的模式,其定義爲:將一個請求封裝成一個對象,從而讓你使用功能不一樣的請求把客戶端參數化,對請求排列或記錄請求日誌,能夠提供命令的撤銷和恢復功能。

>>命令模式示例代碼<<

2三、解釋器模式

  解釋器模式定義:給定一門語言, 定義它的文法的一種表示, 並定義一個解釋器, 該解釋器使用該表示來解釋語言中的句子。

 

參考:

  一、《設計模式之禪》

  二、《設計模式-可複用面對對象軟件的基礎》

  三、https://github.com/luoxn28/ThinkInTechnology/tree/master/DesignPattern

相關文章
相關標籤/搜索