接口隔離原則,到底什么需要隔離?
通過前面的文章,SRP限制一個類的變化來源應該是單一的;OCP要求不要隨意修改一個類;LSP則規(guī)范了類的繼承關系。那么接口隔離原則會給我們帶來什么驚喜呢?今天我們就來聊一聊。
什么是接口隔離?
接口隔離原則,Interface segregation principle(ISP),也是 Robert C. Martin提出的 SOLID原則中的一種,老規(guī)矩,還是先看看作者 Robert C. Martin 對接口隔離原則是如何定義的:
Clients should not be forced to depend upon interfaces that they do not use.
在作者對接口隔離原則的定義中強調:不應強迫客戶依賴他們不使用的接口。
在 Java中,我們一直都強調要面向接口編程,足以看出接口在 Java中的重要性。其實, 與單一職責原則類似,接口隔離原則的目標是通過將軟件拆分為多個獨立的部分來減少所需更改的副作用和頻率。
這里的"不應強迫"該如何理解?通常來講"不應強迫" 有2種理解:
- 第一種理解是用戶不能被強迫使用整個接口。
- 第二種理解是用戶只使用接口中的部分方法,其余的方法不能被強迫使用。
顯然,第二種理解比較合理,所以接口隔離原則可以更直白一點的表達成:在接口中,不要放置接口使用者不需要的方法。
站在接口使用者的角度,這樣的設計更加人性化,為什么要增加一些我不需要的依賴負擔呢?
如何實現(xiàn)接口隔離?
假如有一個業(yè)務場景,需要定義一個交通工具的 Transportation類,類中包含設置基本信息(價格,顏色),啟停以及飛行等方法:
public interface Transportation{
void setPrice(double price);
void setColor(String color);
void start();
void stop();
void fly();
}
汽車屬于一種交通工具,因此我們可以定義一個 Car類去實現(xiàn) Transportation類,代碼如下:
public class Car implements Transportation {
@Override
public void setPrice(double price) {
// 價格設置邏輯
}
@Override
public void setColor(String color) {
// 顏色設置邏輯
}
@Override
public void start(){
// 啟動邏輯
}
@Override
public void stop(){
// 停止邏輯
}
@Override
public void fly(){
// 飛行邏輯
}
}
從上面的代碼可以發(fā)現(xiàn)一個問題:Car不能飛行卻要實現(xiàn) fly()方法,為什么?顯然 fly()這個方法是 Car這種交通工具不需要關注的,這就違反了接口隔離原則。
如何解決這個問題呢?
首先,我們將交通工具接口分成多個角色接口,每個角色接口用于特定的行為,在這里我們可以將 Transportation分成 BasicFeature、 Movable、Flyable 三類行為接口。
// 基本屬性, 價格,顏色
public interface BasicFeature{
void setPrice(double price);
void setColor(String color);
}
// Movable 行為, 行駛和停止
public interface Movable {
void start();
void stop();
}
// 飛行 行為
public interface Flyable {
void fly();
}
而 Car只需要關注基本屬性和 Movable行為,代碼如下:
public class Car implements BasicFeature, Movable {
@Override
public void setPrice(double price) {
// 價格設置邏輯
}
@Override
public void setColor(String color) {
// 顏色設置邏輯
}
@Override
public void start(){
// 啟動邏輯
}
@Override
public void stop(){
// 停止邏輯
}
}
Airplane飛機需要關注基本屬性,Movable行為和飛行行為,代碼如下:
public class Airplane implements BasicCFeature, Movable, Flyable {
@Override
public void setPrice(double price) {
// 價格設置邏輯
}
@Override
public void setColor(String color) {
// 顏色設置邏輯
}
@Override
public void start(){
// 啟動邏輯
}
@Override
public void stop(){
// 停止邏輯
}
@Override
public void fly(){
// 飛行邏輯
}
}
通過上面的拆解,我們可以看到每種交通工具只需要關注自己需要的接口就好了,自己不需要的接口就不會被強迫關注,更加不會造成 Car能 fly()這樣不常見的誤區(qū)。
接口隔離和單一職責的比較
接口隔離原則和單一職責原則都是 SOLID設計原則中的重要組成部分,雖然它們有一些相似之處,但它們關注的重點和應用的范圍有所不同,在實際開發(fā)中,很容易搞混淆,因此,這里對這兩個原則做詳細比較。
- 關注點不同 單一職責原則(SRP):關注類的職責劃分,確保每個類只有為一類行為負責,它主要解決的是類內部職責過多導致的復雜性問題。接口隔離原則(ISP):關注接口的設計,確保客戶端只依賴于它們實際需要的方法。它主要解決的是接口過于龐大導致的依賴問題。
- 作用范圍不同 單一職責原則(SRP):作用于類的設計和實現(xiàn)層面,通過分離職責提高類的內聚性。接口隔離原則(ISP):作用于接口的設計層面,通過細化接口減少客戶端的依賴,提高系統(tǒng)的靈活性。
- 實現(xiàn)方法不同 單一職責原則(SRP):通過將一個類的多種職責分離成多個獨立的類來實現(xiàn)。接口隔離原則(ISP):通過將一個大接口分解為多個小接口,讓不同的客戶端依賴于不同的小接口來實現(xiàn)。
因此,接口隔離原則是在遵守單一職責原則的前提下,將接口更加細化。
總結
接口隔離可以提高代碼的可讀性、可維護性和靈活性,減少系統(tǒng)的耦合度,在實際開發(fā)中,合理應用接口隔離原則,可以幫助我們創(chuàng)建高質量的代碼和系統(tǒng)。然而,在應用時需要注意適度細化和明確職責,避免過度設計和接口混亂。