面向对象设计--接口隔离原则
定义
用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口。
- 一个类对一个类的依赖应该建立在最小的接口上
- 建立单一接口,不要建立庞大臃肿的接口
- 尽量细化接口,接口中的方法尽量少
- 注意适度原则,一定要适度细化接口
代码理解
场景
我们假设有这么一个场景,有一批文件需要你处理,文件格式有 txt,csv,xls,xlsx等,有的是让你格式化数据并导出,有的是让你清洗数据并入库。让你用JAVA实现这个处理场景。
错误实现
1.按照正常来说我们会定义处理文件的接口。
/**
* @InterfaceName IFileHandler
* @Description 文件处理接口
* @Author Neal
* @Date 2019/2/28 19:41
* @Version 1.0
*/
public interface IFileHandler {
/**
* 读取文件
*/
void readFile();
/**
* 处理数据
*/
void handlerData();
/**
* 入库
*/
void database();
/**
* 导出
*/
void export();
}
乍眼一看,恩~我们接口定义的很完美,把所有场景中的所有需求都实现了。
但是呢,我们会有这种情况,假如处理txt文件时,让你格式化数据然后到处excel格式的文件(xls,xlsx),处理csv数据时,会让你清洗数据然后入库。那么我们在这个接口的基础上需要怎么做呢?
2.创建txt处理类
/**
* @ClassName TxtHandler
* @Description 处理txt文件的类
* @Author Neal
* @Date 2019/2/28 19:45
* @Version 1.0
*/
public class TxtHandler implements IFileHandler {
public void readFile() {
System.out.println("读取txt文件");
}
public void handlerData() {
System.out.println("格式化数据");
}
public void database() {
//不做任何操作
}
public void export() {
System.out.println("导出excel");
}
}
3.创建csv处理类
/**
* @ClassName TxtHandler
* @Description 处理CSV文件的类
* @Author Neal
* @Date 2019/2/28 19:45
* @Version 1.0
*/
public class CsvHandler implements IFileHandler {
public void readFile() {
System.out.println("读取csv文件");
}
public void handlerData() {
System.out.println("清洗数据");
}
public void database() {
System.out.println("数据导入数据库");
}
public void export() {
//不做任何操作
}
}
我们来看一下类图
interfaceisolation类图1.png虽然我们都继承了IFileHandler接口,但是我们看到在处理不同文件的时候,有其他接口根本没有用上,但是也暴露给了外面,这样会造成方法冗余。不符合接口隔离原则。
正确实现
1.定义三个接口,分别是 处理文件接口(IFileHandler
),数据导出接口(IDataExport
),数据入库接口(IDataIntoDataBase
)。
IFileHandler:
/**
* @InterfaceName IFileHandler
* @Description 文件处理接口
* @Author Neal
* @Date 2019/2/28 19:41
* @Version 1.0
*/
public interface IFileHandler {
/**
* 读取文件
*/
void readFile();
/**
* 处理数据
*/
void handlerData();
}
IDataExport:
/**
* @InterfaceName IDataExport
* @Description 数据导出接口
* @Author Neal
* @Date 2019/2/28 19:55
* @Version 1.0
*/
public interface IDataExport {
/**
* 导出
*/
void export();
}
IDataIntoDataBase:
/**
* @InterfaceName IDataIntoDataBase
* @Description 数据入库接口
* @Author Neal
* @Date 2019/2/28 19:56
* @Version 1.0
*/
public interface IDataIntoDataBase {
/**
* 入库
*/
void database();
}
2.创建txt处理类,实现文件处理接口和数据导出接口.
/**
* @ClassName TxtHandler
* @Description 处理txt文件的类
* @Author Neal
* @Date 2019/2/28 19:45
* @Version 1.0
*/
public class TxtHandler implements IFileHandler,IDataExport {
public void readFile() {
System.out.println("读取txt文件");
}
public void handlerData() {
System.out.println("格式化数据");
}
public void export() {
System.out.println("导出excel");
}
}
3.创建csv处理类,实现文件处理接口,数据入库接口
/**
* @ClassName TxtHandler
* @Description 处理CSV文件的类
* @Author Neal
* @Date 2019/2/28 19:45
* @Version 1.0
*/
public class CsvHandler implements IFileHandler,IDataIntoDataBase {
public void readFile() {
System.out.println("读取csv文件");
}
public void handlerData() {
System.out.println("清洗数据");
}
public void database() {
System.out.println("数据入库");
}
}
这种实现就比较符合接口隔离原则,将接口尽量细化,因为细粒度我们可以进行组装而粗粒度我们无法拆分。针对不同的操作,对应实现相应的接口,提高扩展性。
我们再来看一下类图就更明显了。
interfaceisolation类图2.png我们可以看到虽然我们定义了三个接口,但是我们细化了接口,所以可以是实现类进行灵活组装。
单一职责原则和接口隔离原则的区别
单一职责原则 | 接口隔离原则 | |
---|---|---|
特性 | 类,接口,方法的职责是单一的,强调职责,也就是在一个类中,只要职责是单一的,有多个方法也没关系。 | 对接口依赖的隔离 |
约束 | 约束的是类,接口,方法,针对程序中的实现和细节。 | 针对抽象,针对程序整体框架的约束。 |
总结
虽然接口隔离原则是尽量让接口细化,但是我们一定要适度,不要盲目的增多接口,徒增麻烦,所以在程序设计的时候一定要做全面的考量和细化。