接口隔离原则
定义:
客户端不应该依赖它不需要的接口
类间的依赖关小应该建立在最小的接口上
什么是接口?
1.实例接口:
Person zhangsan = new Person();
类Person就是zhangsan的实例接口。
2.类接口,就是通常意义上,用interface关键字定义的接口。
解释:
根据接口隔离原则的定义:事实上就是建立单一接口,不要建立臃肿的接口。接口尽量细化,同时接口中的方法尽量少。
接口隔离原则和单一职责原则
接口隔离原则讲的是不论是实例接口也好,还是类接口也好,都要做到尽量细化
但是注意接口隔离原则和单一职责原则不同,单一职责是从业务逻辑角度去定义接口,
比如SelectInterface,UpdateInterface,这是单一职责原则,按查询分,按更新分,这里面可能有10个查询方法,10个更新方法。
但是接口隔离原则的出发点的是尽量使用多个专门的接口
例如,在SelectInterface中有10个方法,其中有5个方法是与查询user相关的,有两个方法是查询role相关的,有两个方法是查询perms相关的,当某个类的业务逻辑不仅仅只和user相关的时候,这个时候就不符合接口隔离原则。
接口隔离原则设计
定义一个美女,需要好身材,好面孔,好气质,那就可以设计这样的接口
public interface IPettyGirl {
/**
* 好面孔
*/
public void goodLooking();
/**
* 好身材
*/
public void niceFigure();
/**
* 好气质
*/
public void goodTemperament();
}
定义一个星探,展示这个美女。
public abstract class AbstractSearcher {
protected IPettyGirl iPettyGirl;
public AbstractSearcher(IPettyGirl iPettyGirl) {
this.iPettyGirl = iPettyGirl;
}
/**
* 展示美女
*/
public abstract void show();
}
实现美女类和星探类,并测试。
public class PettyGirl implements IPettyGirl {//IGoodBodyGirl,IGoodTemperament
/**
* 姓名
*/
private String name;
public PettyGirl(String name) {
this.name = name;
}
@Override
public void goodLooking() {
System.out.println(this.name + "---------有好面孔");
}
@Override
public void niceFigure() {
System.out.println(this.name+"-------------有好身材");
}
@Override
public void goodTemperament() {
System.out.println(this.name + "---------有好气质");
}
}
public class Searcher extends AbstractSearcher {
public Searcher(IPettyGirl iPettyGirl) {
super(iPettyGirl);
}
@Override
public void show() {
System.out.println("美女的信息如下:------------------");
super.iPettyGirl.goodLooking();
super.iPettyGirl.niceFigure();
super.iPettyGirl.goodTemperament();
}
}
public class Client {
public static void main(String[] args) {
IPettyGirl iPettyGirl = new PettyGirl("迪丽热巴");
AbstractSearcher searcher = new Searcher(iPettyGirl);
searcher.show();
}
}
展示了迪丽热巴是个美女。那现在问题来了,这是一个好的接口设计吗?如果有人认为好面孔,好身材是美女,不一定需要好气质。或者有人认为只要好气质就是美女。
那么实现IPettyGirl接口中goodTemperament方法而不实现其他方法?这样做是不行的。那么我们根据接口隔离原则来拆分接口。
public interface IGoodBodyGirl {
/**
* 好面孔
*/
public void goodLooking();
/**
* 好身材
*/
public void niceFigure();
}
public interface IGoodTemperament {
/**
* 好气质
*/
public void goodTemperament();
}
这样拆分接口,那么迪丽热巴还是一个好面孔,好身材,好气质的美女。它就需要实现两个接口。
public class PettyGirl implements IGoodBodyGirl,IGoodTemperament{
/**
* 姓名
*/
private String name;
public PettyGirl(String name) {
this.name = name;
}
@Override
public void goodLooking() {
System.out.println(this.name + "---------有好面孔");
}
@Override
public void niceFigure() {
System.out.println(this.name+"-------------有好身材");
}
@Override
public void goodTemperament() {
System.out.println(this.name + "---------有好气质");
}
}
这样设计接口,在需要扩展的时候,就方便修改了。如果她不是好气质的美女,只需要删掉IGoodTemperament接口的实现即可。
接口隔离原则的目的
保持接口的纯洁性。
具体规范要求有以下4点:
1.接口尽量小
这是核心定义,不出现臃肿的接口,但是小是有限度的,不能无限小,根据接口隔离原则拆分接口时,首先要满足单一职责原则
2.接口要高内聚,减少对外交互,将不需要对外公布的方法设计为非public方法,接口是对外的承诺,承诺越少越有利于系统的安全
3.定制服务
只提供访问者需要的方法,不提供访问者不需要的方法或其他方法
4.接口设计有限度,不能臃肿,也不能无限小
接口隔离原则的实现也是有难度的,给出4点建议:
1.一个接口只服务于一个子模块,比如UserService,只用于处理用户登录,登出等跟用户相关的操作
2.通过业务逻辑压缩public方法
3.已经污染了的接口,尽量修改,如果修改风险过大,使用适配器模式
4.了解环境,环境不同,接口的拆分标准就不同,深入了解业务逻辑,才能设计更好的接口