SOLID原則

最近在準備面試,看到了這個題目,參考了諸多的博客總結以下。java

 

S:single Responsibility Principle 單一職責原則面試

一個類只負責一個職責,當且僅當這個職責需求發生變化時,才須要修改這個類。若是有超出這個職責以外的事情,應當從新將職責分離出去。或經過has-a的方式使用新的職責。
單一職責要求一個類只能有一個發生變化的理由,不容許持有超過自身的其餘功能,由於若是一個類承擔了太多的事情,就會致使抽象體系崩潰,沒法知道這個類到底是什麼。更重要的是,一旦有一個職責須要修改,就對這個類的其餘功能產生影響,這給軟件系統帶來很大的不穩定性。
在工廠模式中,當工廠試圖承擔超過自身能力的類的實例化功能時,就必需要修改代碼,增長判斷或者是其餘操做,一旦有需求須要增長,就須要不斷增長判斷,這一點也違背了開閉原則,所以就須要抽象工廠來對工廠進行抽象。從而分離出具體工廠的職責。下降耦合度。
 
O open close Principle 開閉原則
一個類或者軟件系統,應當是對擴展開放,對修改關閉的。
對於一個類來講,若是須要修改或者增長新功能,那必須是擴展原有代碼,而不是修改原有代碼來實現。由於當項目足夠大,且多人合做的時候,咱們很難肯定某一個類被多少其餘類使用過,也不知道這個類中的方法究竟承擔了怎樣的職責,若是貿然修改它,將會對軟件系統形成不可預知的影響。並且,當有需求頻繁變動的時候,咱們也不可能每一次都修改方法,而且評估這個修改對軟件系統的影響。若是有修改回退,咱們還要找到以前的代碼再改回來。(固然對於這種修改來講,抽象是一種很是有效的辦法。就是增長一個抽象層,抽象層定義行爲,而子類去實現具體的邏輯,這個抽象對客戶端是透明的,客戶端不須要知道怎麼實現,是須要使用便可)
對一個軟件系統來講,也是對open close的。好比咱們提供了一個工具類api,api要保證在每個客戶機上的功能都是不能被修改的,當須要修改或者增長功能時,就須要api開放一些接口,用於客戶機實現具體的定製需求,而這些接口就是一個行爲上固定的抽象層。
 
L 里氏替換原則
   在軟件領域內,is-a的關係並不必定是現實中的關係,軟件內只有當全部子類出現的地方均可以代替爲父類而對軟件沒有影響時,才能說子類與父類有is-a的關係。
  這個典型的反例就是:生物學上企鵝是鳥,可是軟件系統內,若是要對鳥抽象一個會飛的功能,那麼企鵝就不是鳥,由於企鵝不會飛。
  java中常常會有父類型的引用指向子類型的對象,這樣咱們就能夠用統一的父類型,做爲抽象層對外的表現,而使用具體的子類實現具體的功能。當須要增長功能時,也只須要增長一個子類,客戶端調用的代碼甚至都不須要改變。很大程度上實現了代碼的複用。對於接口來講,它只須要約定行爲,這樣就實現了抽象和解耦。
  可是這種特性是須要父類和子類擁有is-a的關係,而不只僅是一個extends關鍵字。假如在子類型中用了父類型沒有的方法,在作里氏替換時就會出錯,如此類繼承體系就會出問題,既然子類not is a 父類了,
 
上面說法有問題,以前沒有理解清楚。
嚴格定義:
1.若是對每個類型爲T1的對象o1,都有類型爲T2的對象o2,使得以T1定義的全部程序P在全部的對象o1都換成o2時,程序P的行爲沒有變化,那麼類型T2是類型T1的子類型。
2.若是對每個類型爲 T1的對象 o1,都有類型爲 T2 的對象o2,使得以 T1定義的全部程序 P 在全部的對象 o1 都代換成 o2 時,程序 P 的行爲沒有發生變化,那麼類型 T2 是類型 T1 的子類型。
通俗定義:全部引用基類的地方必須能透明地使用其子類的對象。
理解:java中,常常有經過父類型的引用指向子類型的對象,在作抽象層的時候每每也會只操做抽象類或者接口,可是在實際運行的時候,操做的是真正的子類型。也就是說,運行時這個子類型寫成父類型是沒有問題的。能夠在編譯期只用父類型。這樣咱們在使用中就不須要考慮抽象類和接口到底是怎麼實現的,實現了多態。
可是想用這種特性,就必需要符合子類is a 父類,里氏替換原則。表現上就是,子類型不要修改重寫父類型已經實現的方法,由於若是這樣作,父類型和子類型的行爲就會出現誤差,從而不能構建is a關係。原本繼承是緊耦合的方式,想要使用繼承也是處於代碼複用了抽象的角度考慮的,那麼父類型給定義的辦法,必定是一種對子類型都有效的約束,子類型隨意篡改父類型的內容是不容許的。也就是說父類型有的子類型也必定要有,且行爲同樣,子類型能夠有本身的辦法。好比子類型企鵝若是但願本身is a 鳥的話,那麼必需要實現鳥的fly方法,可是企鵝實際上不會飛,因此,軟件層面上考慮,企鵝不能是鳥。
博客說,里氏替換是實現開閉的重要原則,可能指的是,當又須要修改或者增長功能時,能夠經過增長一個子類來實現,而軟件表現上仍然能夠用父類型的對象操做。這就是多態,而想要實現這種便利,就必需要產生is a的關係。
參考資料:
 
I interface Segregation Principle 接口隔離原則
這個和單一職責有些相似,意思是一個接口表示一個抽象,它的實現類就是子類,子類要擁有單一職責,所以接口也要符合單一職責,固然這裏的單一職責並非說只有一個方法。
一個接口不該該有太多的內容,若是子類沒有用到其中的某些方法,但仍是須要實例化它們,就會顯得多餘而容易出錯,若是接口方法要發生某種變動,也會致使無關的子類也被影響。既然要重用,那麼保證接口粒度足夠小,才能被很好的重用。
 
D dependence Inversion Principle 依賴倒置原則
定義:高層模塊不該該依賴於底層模塊,兩者都應該依賴於抽象,抽象不該該依賴於細節,細節應該依賴於抽象。
其實就是軟件分層和抽象的內容,高層模塊通常指涉及到具體業務,容易變動的模塊,底層模塊是指更加底層一點,變化較少,一變化會對許多高層模塊產生影響的模塊。也就是說
具體的業務要依賴於提供底層服務的模塊,而不能本身玩本身的。不管是高層仍是底層,都不該該直接用具體的實現類操做,而須要依賴於抽象,抽象在高層底層和更底層之間架設了一箇中間層,架構師抽象這個中間層,提供一個相對穩定的功能,和能夠擴展的接口。這樣就保證了每一層之間儘可能少地耦合。
 
 
開閉原則是目標,里氏代換原則是基礎,依賴倒轉原則是手段
相關文章
相關標籤/搜索