如需下載源碼,請訪問
https://github.com/fengchuanfang/Interface_Segregation_Principle
文章原創(chuàng),轉(zhuǎn)載請注明出處:
設計模式心法之接口隔離原則
接口隔離原則(ISP,Interface Segregation Principle)
——設計模式基本原則之一
定義:
客戶端不應該依賴它不需要的接口(Clients should not be forced to depend upon interfaces that they don't use)
類間的依賴關(guān)系應該建立在最小的接口上(The dependency of one class to another one should depend on the smallest possible interface)
接口是靜態(tài)常量和抽象方法的集合,既是其引用持有類依賴關(guān)系的協(xié)議,也是其實現(xiàn)類的規(guī)范。接口的設計在一個項目的開發(fā)中起到舉足輕重的作用,是使項目保持良好拓展性的關(guān)鍵。
接口隔離原則要求我們在設計接口時,要使用多個專門的接口不要使用單一的龐大臃腫的總接口,一個類對另一個類的依賴性應該建立在最小的接口上。要做到接口與角色一一對應,不應該讓一個接口承擔多個角色,也不應該讓一個角色由多個接口承擔。這樣設計的接口在應對未來變更時,會更具有靈活性和可拓展性。
有一工廠接口對外提供原料預處理(preProcess),半成品加工(processA1,processA2,processB1,processB2),產(chǎn)品包裝(packaging)等方法,如下:
public interface IFactory {
String preProcess(String material);
String processA1(String semis);
String processA2(String semis);
String processB1(String semis);
String processB2(String semis);
String packaging(String product);
}
場景類ClientA通過接口IFactory依賴類FactoryA中的preProcess,processA1,processA2,packaging方法,代碼如下:
public class ClientA {
public static void main(String args[]) {
IFactory factory = new FactoryA();
String semis1 = factory.preProcess("原料");
String semis2 = factory.processA1(semis1);
String product = factory.processA2(semis2);
System.out.println(factory.packaging(product));
}
}
public class FactoryA implements IFactory {
@Override
public String preProcess(String material) {
return material + "-->預處理";
}
@Override
public String processA1(String semis) {
return semis + "-->a1工序半成品加工";
}
@Override
public String processA2(String semis) {
return semis + "-->a2工序半成品加工";
}
@Override
public String processB1(String semis) {
return null;
}
@Override
public String processB2(String semis) {
return null;
}
@Override
public String packaging(String product) {
return product + "-->包裝成品";
}
}
運行結(jié)果如下:
原料-->預處理-->a1工序半成品加工-->a2工序半成品加工-->包裝成品
場景類ClientB通過接口IFactory依賴類FactoryB中的preProcess,processB1,processB2,packaging方法,代碼如下:
public class ClientB {
public static void main(String[] args) {
IFactory factory = new FactoryB();
String semis1 = factory.preProcess("原料");
String semis2 = factory.processB1(semis1);
String product = factory.processB2(semis2);
System.out.println(factory.packaging(product));
}
}
public class FactoryB implements IFactory {
@Override
public String preProcess(String material) {
return material + "-->預處理";
}
@Override
public String processA1(String semis) {
return null;
}
@Override
public String processA2(String semis) {
return null;
}
@Override
public String processB1(String semis) {
return semis + "-->b1工序半成品加工";
}
@Override
public String processB2(String semis) {
return semis + "-->b2工序半成品加工";
}
@Override
public String packaging(String product) {
return product + "-->包裝成品";
}
}
運行結(jié)果如下:
原料-->預處理-->b1工序半成品加工-->b2工序半成品加工-->包裝成品
在上述示例中,接口IFactory對于類ClientA和ClientB來說,均不是最小接口,IFactory中存在著類ClientA和ClientB使用不到的方法。但是作為IFactory的實現(xiàn)類FactoryA和FactoryB不得不去實現(xiàn)場景類中使用不到的方法。
IFactory作為場景類ClientA,ClientB依賴對應工廠類FactoryA,FactoryB之間的協(xié)議過于繁瑣,作為其子類FactoryA,FactoryB的規(guī)范過于臃腫,這種設計顯然太過于死板而不夠靈活。如果以后因需求變更過大,無論場景類ClientA還是ClientB所依賴的接口需要更改,都會導致另一個場景類所依賴的接口實現(xiàn)類去實現(xiàn)場景類中使用不到的方法來適應這種變更,
我們可以按照接口隔離原則將IFactory拆分成以下三個接口,
public interface ISubFactory {
String preProcess(String material);
String packaging(String product);
}
public interface IFactoryA {
String processA1(String semis);
String processA2(String semis);
}
public interface IFactoryB {
String processB1(String semis);
String processB2(String semis);
}
然后由類FactoryA實現(xiàn)接口ISubFactory和IFactoryA,代碼如下:
public class FactoryA implements ISubFactory,IFactoryA{
@Override
public String preProcess(String material) {
return material + "-->預處理";
}
@Override
public String processA1(String semis) {
return semis + "-->a1工序半成品加工";
}
@Override
public String processA2(String semis) {
return semis + "-->a2工序半成品加工";
}
@Override
public String packaging(String product) {
return product + "-->包裝成品";
}
}
場景類中代碼如下:
public class ClientA {
public static void main(String[] args) {
ISubFactory subFactory = new FactoryA();
IFactoryA factory = new FactoryA();
String semis1 = subFactory.preProcess("原料");
String semis2 = factory.processA1(semis1);
String product = factory.processA2(semis2);
System.out.println(subFactory.packaging(product));
}
}
運行結(jié)果如下:
原料-->預處理-->a1工序半成品加工-->a2工序半成品加工-->包裝成品
由類FactoryB實現(xiàn)接口ISubFactory和IFactoryB,代碼如下:
public class FactoryB implements ISubFactory, IFactoryB {
@Override
public String preProcess(String material) {
return material + "-->預處理";
}
@Override
public String processB1(String semis) {
return semis + "-->b1工序半成品加工";
}
@Override
public String processB2(String semis) {
return semis + "-->b2工序半成品加工";
}
@Override
public String packaging(String product) {
return product + "-->包裝成品";
}
}
場景類中代碼如下:
public class ClientB {
public static void main(String[] args) {
ISubFactory subFactory = new FactoryB();
IFactoryB factory = new FactoryB();
String semis1 = subFactory.preProcess("原料");
String semis2 = factory.processB1(semis1);
String product = factory.processB2(semis2);
System.out.println(subFactory.packaging(product));
}
}
運行結(jié)果如下:
原料-->預處理-->b1工序半成品加工-->b2工序半成品加工-->包裝成品
相同的運行結(jié)果下,實現(xiàn)類FactoryA和FactoryB中均不存在其場景類中使用不到的方法,如果以后因需求變化過大,更改接口IFactoryA,也不會對實現(xiàn)類FactoryB造成任何影響。這樣設計的接口在應對未來變更時,會更具有靈活性和可拓展性。