概述
接口隔离原则(Inteface Segregation Principle,ISP)指设计时不同的功能应定义在不同的接口上或按照功能划分定义多个专门的接口而不是使用单一的总接口,避免实现类依赖不需要的接口(方法),换个角度理解就是一个类应该依赖尽量少的接口或实现类,减少程序的冗余性和复杂性。
深入理解
接口隔离原则指导架构设计人员在设计接口时应当注意以下关键点
- 一个类对另外一个类(接口的实现类)的依赖应该建立在最小的接口之上
- 可以建立多个专门的接口,不要建立一个庞大臃肿的接口
- 适当划分接口功能,接口的方法尽量少(适度)
代码示例
下面以品牌汽车为例,对其行为进行抽象描述。
- 汽车接口
// 汽车接口
public interface Car {
// 启动
void start();
// 行驶
void run();
// 加油
void refuel();
// 充电
void charge();
}
// 哈弗VV7燃油车
public class HavalVV7 implements Car{
@Override
public void start() {
// 一键启动
}
@Override
public void run() {
// 挂挡、踩油门
}
@Override
public void refuel() {
// 先停车、熄火
}
@Override
public void charge() {
// 纯燃油车,不充电
}
}
- 哈弗VV7汽车
// 哈弗VV7燃油车
public class HavalVV7 implements Car{
@Override
public void start() {
// 一键启动
}
@Override
public void run() {
// 挂挡、踩油门
}
@Override
public void refuel() {
// 先停车、熄火
}
@Override
public void charge() {
// 纯燃油车,不充电
}
}
- 特斯拉Model3
// 特斯拉Model3
public class TeslaModel3 implements Car {
@Override
public void start() {
// 一键启动
}
@Override
public void run() {
// 挂挡、踩油门
}
@Override
public void refuel() {
// 纯电动车,不加燃油
}
@Override
public void charge() {
// 先停车、熄火
}
}
- 丰田双引擎凯美瑞
// 丰田双擎凯美瑞
public class ToyotaCamry implements Car {
@Override
public void start() {
// 钥匙启动
}
@Override
public void run() {
// 挂挡、踩油门
}
@Override
public void refuel() {
// 先停车、熄火、加燃油
}
@Override
public void charge() {
// 先停车、熄火、双引擎的车也可以充电
}
}
以上的示例中,哈弗VV7是纯燃油车,没有充电行为;与之相反的是特斯拉Model3其是纯电动汽车,没有加注燃油的行为;而丰田凯美瑞由于是双引擎(汽油+电池)汽车,既可以加注燃油,也可以充电。可以看到不同品牌不同车型,有些方法是不需要实现的,此时可以针对不同类型的车型的行为特性分别设计接口。
- 重构原有的汽车接口,保留公共行为特性
// 汽车接口
public interface Car {
// 启动
void start();
// 行驶
void run();
}
- 增加燃油车接口和电动车接口
// 燃油车
public interface OilCar extends Car{
// 加油 void refuel();
}
// 电动汽车
public interface ElectricCar extends Car {
// 充电
void charge();
}
- 重构三种汽车:重构之后的接口复用性更高了
// 哈弗VV7燃油车:只实现燃油车接口即可
public class HavalVV7 implements OilCar{
@Override public void start() {
// 一键启动 }
@Override public void run() {
// 挂挡、踩油门 }
@Override public void refuel() {
// 先停车、熄火 }
}
// 特斯拉Model3:只实现电动车接口即可
public class TeslaModel3 implements ElectricCar {
@Override
public void start() {
// 启动
}
@Override
public void run() {
// 挂挡、踩油门
}
@Override
public void charge() {
// 先停车、熄火
}
}
// 丰田双擎凯美瑞:同时实现燃油车和电动车
public class ToyotaCamry implements OilCar,ElectricCar {
@Override
public void start() {
// 钥匙启动
}
@Override
public void run() {
// 挂挡、踩油门
}
@Override
public void refuel() {
// 先停车、熄火、加燃油
}
@Override
public void charge() {
// 先停车、熄火、双引擎的车也可以充电
}
}
总结
接口隔离原则符合高内聚、低耦合的设计思想,可以使类具有很好的可读性、复用性、可扩展性和可维护性。在设计接口时,要多花时间去思考,考虑业务模型,包括对以后有可能发生变更的地方作预判等。