標籤:temp 建構函式 interface 過多 工作 傳遞依賴 包含 upload strategy
JAVA 設計模式遵循的六大基本準則一、單一職責原則:(Single Responsibility Pinciple)
一個類只負責一項職責。 當超過一項職責需要負責時,需要增加新的類來負責新的職責,而不是在類中個性代碼。
如果一個類承擔的職責太多,就是高度地職責耦合,非常不利於擴充功能。這是非常脆弱的設計。 容易發生修改一個地方而影響其他地方的情況。
遵循單一職責原則的優點:
- 降低類的複雜度
- 提高類的可讀性,提高系統的可維護性
- 變更引起的風險降低
二、裡氏代換原則:(Liskov Substitution Principle,簡稱LSP)子類可以擴充父類的功能,但不能改變父類原有的功能
裡氏代換原則(Liskov Substitution Principle, LSP):所有引用基類(父類)的地方必須能透明地使用其子類的對象。
裡氏代換原則告訴我們,在一個軟體系統中,子類應該可以替換任何基類能夠出現的地方,並且經過替換以後,代碼還能正常工作。子類也能夠在基類的基礎上增加新的行為。
例如有兩個類,一個類為BaseClass,另一個是SubClass類,並且SubClass類是BaseClass類的子類,那麼一個方法如果可以接受一個BaseClass類型的基類對象base的話,如:method1(base),那麼它必然可以接受一個BaseClass類型的子類對象sub,method1(sub)能夠正常運行。反過來的代換不成立,如一個方法method2接受BaseClass類型的子類對象sub為參數:method2(sub),那麼一般而言不可以有method2(base),除非是重載方法。
裡氏代換原則是實現開閉原則的重要方式之一,由於使用基類對象的地方都可以使用子類對象,因此在程式中盡量使用基類類型來對對象進行定義,而在運行時再確定其子類類型,用子類對象來替換父類對象。
包含4層含義:
- 子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法。
- 子類中可以增加自己特有的方法。
- 當子類的方法重載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬鬆。
- 當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的傳回值)要比父類更嚴格。
不遵循裡氏代換原則的後果是,寫代碼出錯的機率會大大增加。
三、依賴倒置原則(Dependence Inversion Principle,簡稱DIP)
定義:1.高層模組不應該依賴低層模組,二者都應該依賴其抽象; 2.抽象不應該依賴細節;細節應該依賴抽象。
問題由來:類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的代碼來達成。這種情境下,類A一般是高層模組,負責複雜的商務邏輯;類B和類C是低層模組,負責基本的原子操作;假如修改類A,會給程式帶來不必要的風險。
解決方案:將類A修改為依賴介面I,類B和類C各自實現介面I,類A通過介面I間接與類B或者類C發生聯絡,則會大大降低修改類A的幾率。
依賴倒置原則基於這樣一個事實:相對於細節的多變性,抽象的東西要穩定的多。以抽象為基礎搭建起來的架構比以細節為基礎搭建起來的架構要穩定的多。在java中,抽象指的是介面或者抽象類別,細節就是具體的實作類別,使用介面或者抽象類別的目的是制定好規範和契約,而不去涉及任何具體的操作,把展現細節的任務交給他們的實作類別去完成。
傳遞依賴的三種寫法:
1.建構函式傳遞依賴對象
2.Setter方法傳遞依賴對象
3.介面聲明傳遞依賴對象
深入瞭解可以看:輕鬆學,淺析依賴倒置(DIP)、控制反轉(IOC)和依賴注入(DI)
四、介面隔離原則(Interface Segregation Principle,簡稱ISP)
- 核心思想:類間的依賴關係應該建立在最小的介面上
- 通俗來講:建立單一介面,不要建立龐大臃腫的介面,盡量細化介面,介面中的方法盡量少。也就是說,我們要為各個類建立專用的介面,而不要試圖去建立一個很龐大的介面供所有依賴它的類去調用。
舉例 問題由來:類A通過介面I依賴類B,類C通過介面I依賴類D,如果介面I對於類A和類B來說不是最小介面,則類B和類D必須去實現他們不需要的方法。
舉例來說明介面隔離原則:
(圖1 未遵循介面隔離原則的設計)
這個圖的意思是:類A依賴介面I中的方法1、方法2、方法3,類B是對類A依賴的實現。類C依賴介面I中的方法1、方法4、方法5,類D是對類C依賴的實現。對於類B和類D來說,雖然他們都存在著用不到的方法(也就是圖中紅色字型標記的方法),但由於實現了介面I,所以也必須要實現這些用不到的方法。
解決方案:將臃腫的介面I拆分為獨立的幾個介面,類A和類C分別與他們需要的介面建立依賴關係。也就是採用介面隔離原則。
可以看到,如果介面過於臃腫,只要介面中出現的方法,不管對依賴於它的類有沒有用處,實作類別中都必須去實現這些方法,這顯然不是好的設計。如果將這個設計修改為符合介面隔離原則,就必須對介面I進行拆分。在這裡我們將原有的介面I拆分為三個介面,拆分後的設計2所示:
(圖2 遵循介面隔離原則的設計)
- 需注意:
- 介面盡量小,但是要有限度。對介面進行細化可以提高程式設計靈活性,但是如果過小,則會造成介面數量過多,使設計複雜化。所以一定要適度
- 提高內聚,低耦合=減少對外互動。每個模組儘可能獨立完成自己的功能,不依賴於模組外部的代碼。內聚和耦合是密切相關的,同其他模組存在高耦合的模組意味著低內聚,而高內聚的模組意味著該模組同其他模組之間是低耦合。在進行軟體設計時,應力爭做到高內聚,低耦合。
- 為依賴介面的類定製服務。只暴露給調用的類它需要的方法,它不需要的方法則隱藏起來。只有專註地為一個模組提供定製服務,才能建立最小的依賴關係。
五、迪米特法則(Law of Demeter,簡稱LoD)
迪米特法則有很多種說法,比如:一個類應該應該對其他類儘可能瞭解得最少;類只與直接的朋友通訊等等。但是其最終目的只有一個,就是讓類間解耦。
定義
- 迪米特法則:Law Of Demeter,LoD。
- 也被稱為最少知識原則,Least Knowledge Principle,LKP。
就是說一個對象應該對其他對象保持最少的瞭解。正如最少知識原則這個定義一樣,一個類應該對其耦合的其他類或所調用的類知道得最少。所耦合的類內部無論如何複雜,怎麼實現的我都不需要知道,我只調用你public出來的這些方法,其他都不用知道。
參考文檔-迪米特法則
六、開放封閉原則(Open Close Principle,簡稱OCP)
所謂開放封閉原則就是軟體實體應該對擴充開放,而對修改封閉。開放封閉原則是所有物件導向原則的核心。軟體設計本身所追求的目標就是封裝變化,降低耦合,而開放封閉原則正是對這一目標的最直接體現。
開放封閉原則主要體現在兩個方面:
- 對擴充開放,意味著有新的需求或變化時,可以對現有代碼進行擴充,以適應新的情況。
- 對修改封閉,意味著類一旦設計完成,就可以獨立其工作,而不要對類盡任何修改。
為什麼要用到開放封閉原則呢?
軟體需求總是變化的,世界上沒有一個軟體的是不變的,因此對軟體設計人員來說,必須在不需要對原有系統進行修改的情況下,實現靈活的系統擴充。
如何做到對擴充開放,對修改封閉呢?
實現開放封閉的核心思想就是對抽象編程,而不對具體編程,因為抽象相對穩定。讓類依賴於固定的抽象,所以對(抽象類別)修改就是封閉的;而通過物件導向的繼承和多態機制,可以實現對抽象體的繼承,通過覆寫其方法來改變固有行為,實現新的擴充方法,所以對於擴充就是開放的。
對於違反這一原則的類,必須通過重構來進行改善。常用於實現的設計模式主要有Template Method模式和Strategy 模式。而封裝變化,是實現這一原則的重要手段,將經常變化的狀態封裝為一個類。
代碼參考例子:以銀行業務員為例
總結:
- 單一職責原則告訴我們實作類別要職責單一;
- 裡氏替換原則告訴我們不要破壞繼承體系;
- 依賴倒置原則告訴我們要面向介面編程;
- 介面隔離原則告訴我們在設計介面的時候要精簡單一;
- 迪米特法則告訴我們要降低耦合。而開閉原則是總綱,他告訴我們要對擴充開放,對修改關閉。
JAVA 設計模式遵循的六大基本準則