里氏替換原則 (LSP)#
定義:所有引用父類的地方,必須能使用子類的對象丽蝎。簡單地說就是將父類替換為他的子類是不會出現(xiàn)問題,反之膀藐,未必可以屠阻。那么里氏替換原則就是依賴于面向?qū)ο笳Z言的繼承與多態(tài)红省。核心原理是抽象。
這里列舉一下繼承的優(yōu)缺點:
優(yōu)點:
(1)代碼重用栏笆,減少創(chuàng)建類的成本类腮,每個子類都擁有父類的方法與屬性。
(2)子類與父類基本相似蛉加,但與父類又有所區(qū)別蚜枢。
(3)提高代碼的可擴展性。
缺點:
(1)繼承是侵入性的针饥,只要繼承就必須擁有父類所有的屬性與方法厂抽。
(2)可能造成子類代碼冗余、靈活性降低,因為子類必須擁有父類的屬性和方法丁眼。
開閉原則和里氏替換原則是生死相依的筷凤、不離不棄的。他們都強調(diào)了抽象這一重要的特性苞七。
示例代碼
public class Window {
public void show(View child){
child.draw();
}
}
public abstract class View {
public abstract void draw();
public void measure(int width,int height){
//測量視圖大小
}
}
public class Button extends View {
@Override
public void draw() {
// 繪制按鈕
}
}
public class TextView extends View {
@Override
public void draw() {
// 繪制文本
}
}
上述示例中藐守,Window依賴于 View,而 View 定義了一個視圖抽象蹂风,measure 是各個子類共享的方法卢厂,子類通過覆寫 View 的 draw 方法實現(xiàn)具有各自特色的功能,在這里這個功能就是繪制自身的內(nèi)容惠啄。任何繼承自 View 類的子類都可以設(shè)置給 show 方法慎恒,就是所說的里氏替換。通過里氏替換撵渡,就可以自定義各式各樣融柬、千變?nèi)f化的 View,然后傳遞給 Window趋距,Window 負責組織 View 并將 View 顯示到屏幕上粒氧。
依賴倒置原則(DIP)
定義:指代一種特定的解耦方式,使得高層次的模塊不依賴于低層次的模塊的實現(xiàn)細節(jié)的目的节腐。他有一下幾個關(guān)鍵點:
(1)高層模塊不依賴于低層模塊靠欢,應(yīng)該都依賴其抽象。
(2)抽象不依賴細節(jié)铜跑。
(3)細節(jié)應(yīng)依賴抽象。
解釋:在Java中骡澈,抽象就是指接口或者抽象類锅纺,兩者都是不能直接被實例化的;細節(jié)就是實現(xiàn)類肋殴,實現(xiàn)接口或者繼承抽象類而產(chǎn)生的就是細節(jié)囤锉,也就是可以加上一個關(guān)鍵字new產(chǎn)生的對象坦弟。高層模塊就是調(diào)用端,底層模塊就是具體實現(xiàn)類官地。依賴倒置原則在Java中的表現(xiàn)就是:模塊間通過抽象發(fā)生酿傍,實現(xiàn)類之間不發(fā)生直接依賴關(guān)系,其依賴關(guān)系是通過接口或者抽象類產(chǎn)生的驱入。如果類與類直接依賴細節(jié)赤炒,那么就會直接耦合血久,那么當修改時捷绒,就會同時修改依賴者代碼,這樣限制了可擴展性传泊。
接口隔離原則(ISP)
定義:類間的依賴關(guān)系應(yīng)該建立在最小的接口上雪情,將龐大遵岩、臃腫的接口拆分成更小的、更具體的接口巡通。目的是系統(tǒng)的解耦尘执,從而更容易重構(gòu)、更改和重新部署宴凉。
示例:
finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
這段代碼我們經(jīng)常見到誊锭,他的可讀性非常的差。我們知道 Java 中有一個 Closeable 接口標識了可關(guān)閉對象跪解,它只有一個 close 方法炉旷,有100多個類實現(xiàn)了這個接口,這意味著在關(guān)閉這100多個類的對象時我們都要寫出上面那一段難看的代碼來關(guān)閉它叉讥,這你能忍窘行?
書中給出的解決方案如下:
既然都實現(xiàn)了Closeable接口,那我們只需要建一個方法來統(tǒng)一關(guān)閉這些對象即可图仓,以下為工具類代碼:
public class Closeutils {
private Closeutils() {
}
/**
* 關(guān)閉Closeable對象
*/
public static void closeQuietly(Closeable closeable) {
if (null != closeable) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
此時關(guān)閉就只需要這樣:
finally {
Closeutils.closeQuietly(fileOutputStream);
}
代碼非常簡潔罐盔,而且只要繼承了 Closeable 接口都可以用此方法關(guān)閉,我們只需要知道這個對象是可關(guān)閉的救崔,其他的一概不關(guān)心惶看,也就是接口隔離原則。
迪米特原則(LOD)
定義:一個類應(yīng)該對自己需要耦合或者調(diào)用的類知道的最少六孵,類的內(nèi)部如何實現(xiàn)與調(diào)用者或者依賴者沒有關(guān)系纬黎,調(diào)用者或依賴者只需知道他需要的方法,其他可以一概不管劫窒。這樣使得系統(tǒng)具有更低的耦合與更好的可擴展性本今。