提及設計模式我想對每個猿友來講都是一個油膩的話題、23中設計模式張口就來。然而對於這些模式的的設計原則你們還能記起多少?瞭解多少以及用到多少尼?下面就讓咱們來一塊兒回顧下。面試
設計模式六大設計原則分別爲、開-閉原則、里氏代換原則、依賴倒轉原則、合成/聚合複用原則、迪米特法則、接口隔離原則等六大設計原則。編程
下面讓咱們一一介紹下他們吧!設計模式
經典力學的基石是牛頓三大定義、而面向對象可複用設計的第一塊基石,即是所謂的「開-閉」原則(open-closed-principle).工具
什麼是「開-閉」原則??????設計
「開-閉」原則講的是:一個軟件實體應當對擴展開放、對修改關閉(膜拜下 Bertrand Meyer)。code
就是說:設計一個模塊時、應當使這個模塊在不被修改的前提下被擴展。對象
程序猿語言:應當能夠在沒必要修改源碼的狀況下改變這個模塊的行爲。繼承
全部的軟件系統有個一共同的特性、即對他的需求會隨着時間的推移而改變(固然這不是程序猿大戰產品的理由)。
在軟件系統面臨新的需求時,系統必須是穩如磐石的。接口
知足「開-閉」原則的設計能夠給一個軟件系統提供兩個無可比擬的優點(少幹架)生命週期
1: 經過擴展已有軟件系統,能夠提供新的行爲、以知足對軟件系統的新需求,使變化中的系統有必定的適應性和靈活性 2: 已有的軟件模塊、特別是抽象層的模塊是萬萬不能在修改的,這就使變化中的軟件系統有必定的穩定性和延續性。
具備這兩個優勢的軟件系統、是一個高層次上實現了複用的系統、也是一個易於維護和擴展的系統。
如何實現「開-閉」原則???
咋看起來、不能修改和能夠擴展是相互矛盾的。怎麼來實現不能修改的同時用能擴展尼???
解決問題關鍵仍是老生常談的抽象化了。咱們都知道Java語言是一個面向對象的語言,咱們能夠給系統定一個一個一勞永逸、再也不修改的抽象層(或者接口),此設計能夠有無窮無盡的行爲實現層來實現。
在Java中咱們能夠抽象出一個或者多個抽象類或者接口、規定出全部具體類(實現類)必須提供的方法特徵做爲系統設計的抽象層。這個抽象層預見了全部可能的擴展,所以在任何擴展狀況下都不會改變。這就使系統的抽象層不須要修改,從而知足「開-閉」原則中的第二條:對修改關閉。
同時、因爲從抽象層派生出一個或者多個具體實現類能夠改變系統的行爲。所以系統的設計對擴展是開放的,這就知足了「開-閉」原則的第一條。
要作到「開-閉」原則不是一件容易的事、可是也不是徹底無規律可循、這些規律也一樣是以設計原則的身份出現,可是他們都是「開-閉」的手段和工具、是附屬於「開-閉」的。
里氏代換原則、依賴倒轉原則、合成/聚合複用原則、迪米特法則、接口隔離原則等。
從「開-閉」原則中能夠看出面向對象設計重要原則是建立抽象化。而且從抽象化導出具體化。
具體化能夠給出不一樣的版本,每個版本都給出不一樣的實現(說直白點就是基類和子類的關係)。
從抽象化到具體化的導出要使用到繼承關係和這裏要引入的里氏代換原則。
什麼是里氏代換原則???
一個軟件實體若是使用的是一個基類的話,那麼必定適用於其子類,並且它根本不能察覺出基類對象和子類對象的區別(也就是說,任何基類出現的地方均可以替換成子類)。
好比: 有兩個類,一個是Base類,另外一個是Derived類,而且Derived類是Base類的子類。
那麼一個方法若是能夠接受一個基類對象base的話method(Base base)那麼它必然能夠接受一個子類對象derived,也就是method(Derived derived)。
注意:里氏代換原則反過來是沒法實現的。
實現「開-閉」原則的關鍵是抽象化、而且從抽象化導出具體實現,如說「開-閉」是面向對象設計的目標的話,依賴倒轉原則是面向對象的設計的主要機制。
依賴倒轉原則講的是: 要依賴於抽象,不要依賴於具體。
什麼是依賴倒轉原則???
簡單的說,依賴倒轉原則要求客戶依賴抽象耦合。
依賴倒轉原則表述的是;細節應當依賴於抽象。
其另外一種表述是:要針對接口編程,不要針對實現編程,
針對接口編程意思是說,應當使用Java接口和抽象類進行變量的類型聲明、參量的類型聲明、方法的返回類型聲明、以及數據類型的轉換等。 不要針對實現編程的意思是說:不該當使用具體類進行變量的類型聲明、參量的類型聲明、方法的返回類型聲明、以及數據類型的轉換等。
要保證作到這一點,一個具體的Java 類應當只實現Java接口或者抽象類中聲明過的方法,而不該當有多餘的方法。
倒轉依賴關係強調一個系統內的實體之間的關係的靈活性。基本上,若是設計師但願遵照「開-閉」原則,那麼倒轉依賴原則即是達到要求的途徑。
接口隔離原則講的是:使用多個專門的接口比使用單一總接口要好。換而言之,從一個客戶類的角度來說,一個類對另外一個的依賴性應當創建在最小的接口上
什麼是接口隔離原則???
使用多個專門的接口比使用單一的總接口要好
一個類對另一個類的依賴性應當是創建在最小的接口上的。
一個接口表明一個角色,不該當將不一樣的角色都交給一個接口。
沒有關係的接口合併在一塊兒,造成一個臃腫的大接口,這是對角色和接口的污染。「不該該強迫客戶依賴於它們不用的方法。
接口屬於客戶,不屬於它所在的類層次結構。」這個說得很明白了,再通俗點說,不要強迫客戶使用它們不用的方法,若是強迫用戶使用它們不使用的方法,那麼這些客戶就會面臨因爲這些不使用的方法的改變所帶來的改變。
合成/聚合複用原則常常又叫作合成複用原則。合成/聚合複用原則就是在一個新對象裏面使用一個已經存在的對象,使之成爲新對象的一部分,新對象經過向這些對象委派達到複用功能的目的。
這個設計原則有另外一個更簡單的表述: 要進儘可能使用合成/聚合,儘可能不要使用繼承。
合成一詞使用比較普遍,常常用易引發混淆。爲了不混淆咱們來簡單的考察下"合成"和「聚合」的區別
1: 合成和聚合均是關聯的特殊種類。 2: 聚合用來表示「擁有」關係或者總體與部分的關係、同時部分能夠單獨存在。 3: 合成則表示一種強的多的「擁有」關係,部分和總體的生命週期是一致的,部分離開總體沒法單獨存活的。好比人是一個總體各個肢體是部分。
迪米特法則又叫最少知道原則,就是說,一個對象應當對其餘對象有儘量少的瞭解。
迪米特法則最初是用來做爲面向對象的系統設計風格的一種法則,1987年秋天由 Ian Holland 在美國東北大學爲一個叫迪米特的項目設計提出的。所以叫作迪米特法則。
迪米特法則的各類表述
沒有任何一個其它的OO設計原則像迪米特法則這樣有如此之多的表述方式,下面是幾種有表明性的表述。
1: 只與你直接的朋友通訊 2: 不要跟「陌生人」說話 3: 每個軟件單位對其的單位都只有最少的瞭解,並且侷限於哪些與本單位密切相關的軟件單位。
在上面表述中裏面,什麼是「直接「,」陌生「和」密切「則被有意識的模糊化了,以便在不一樣的環境下能夠有不一樣的解釋。
這些設計原則都是軟件工程裏面很基礎也很重要的部分,也是咱們開發人員最容易忽略的部分。
做爲面試官的幾年裏,應聘者能完整答上來設計模式的幾大原則或者面向對象設計原則的太少了(包括一些高級和資深)。
若是這幾大原則沒有吃透的話,是不可能設計出一個好的軟件系統的。寫這篇的目的也在於本身回顧加深一下理解。