面向对象的7种设计原则(2)-接口隔离原则
定义
Interface Segregation Principle
-
客户端不应依赖它不需要的接口
-
类间的依赖关系应该建立在最小的接口上
其实通俗来理解就是,不要在一个接口里面放很多的方法,这样会显得这个类很臃肿。接口应该尽量细化,一个接口对应一个功能模块,同时接口里面的方法应该尽可能的少,使接口更加灵活轻便。或许有的人认为接口隔离原则和单一职责原则很像,但两个原则还是存在着明显的区别。单一职责原则是在业务逻辑上的划分,注重的是职责。接口隔离原则是基于接口设计考虑。例如一个接口的职责包含10个方法,这10个方法都放在同一接口中,并且提供给多个模块调用,但不同模块需要依赖的方法是不一样的,这时模块为了实现自己的功能就不得不实现一些对其没有意义的方法,这样的设计是不符合接口隔离原则的。接口隔离原则要求"尽量使用多个专门的接口"专门提供给不同的模块。
由来
类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
举例:
public interface School {
/**
* 上课
*/
void attendClass();
/**
* 下课
*/
void afterClass();
/**
* 学习
*/
void learn();
/**
* 讲课
*/
void lecture();
}
假设此时有一个People类,它的角色是学生,实现了School接口。它就会被迫实现“讲课”这个方法,事实它是不需要该方法的。这就造成了代码的冗余,使我们的代码变得臃肿。
解决
将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。
举例:
学校接口
public interface School {
/**
* 上课
*/
void attendClass();
/**
* 下课
*/
void afterClass();
}
老师接口
public interface Teacher {
/**
* 讲课
*/
void lecture();
}
学生接口
public interface School {
/**
* 学习
*/
void learn();
}
通过上面的拆分我们就可以有效避免冗余代码的产生,进而还可以促使我们的代码变得更加灵活。
优点
避免接口污染
一个类如果要实现一个接口,那么就要实现这个接口要求的所有方法,如果这个接口里面包含这个类不需要的方法,那么就会造成接口污染,这是不好的设计,会对系统留下隐患。
提高灵活性
一个类是可以同时实现多个接口的,所以将一个臃肿的接口分割为若干个小接口,通过小接口的不同组合可以满足更多的需求。
提供定制服务
定制服务就是单独为一个个体提供优良的服务。我们在做系统设计时也需要考虑对系统之间或模块之间的接口提供定制服务。提供定制服务就必然有一个需求:只提供访问者需要的方法。这也是可以通过细化接口实现的。
高内聚
什么是高内聚?高内聚就是提高接口、类、模块的处理能力,减少对外的交互。比如说,你告诉你的下属“一个小时之内去月球搬一块石头回来”,然后你就躺在海滩上晒着太阳喝着果汁,一个小时之后你的下属就搬着一块月亮上的石头回来给你了。这种不讲任何条件,不需要你关心任何细节,立即完成任务的行为就是高内聚的表现。
具体到接口中,还是尽量细化你的接口。接口是对外界的承诺,承诺越少对系统的开发越有利,变更的风险也就越少,同时也有利于降低成本。