4接口隔离原则
接口隔离原则
接口隔离原则的英文名称是:Interface Segregation Principle,简称ISP.
1接口隔离原则的定义
首先明确“接口”的概念,分为两种:
- 实例接口(Object Interface),在Java中声明一个类,然后用new关键字产生一个实例,它是对一个类型的事物所具有的方法特征描述,也称作一个“接口”,这仅是一种逻辑上的抽象。例如,定义一个Person类,使用Person zhangsan = new Person()产生一个实例,该实例遵从的标准是Person这个类,Person就是zhangsan的接口。
- 类接口(class Interface),是指在Java中使用Interface严格定义的接口,例如,Java.lang.Runnable就是Java线程的一个接口。
针对“接口”两种不同的含义,接口隔离原则的表达方式以及含义都有所不同,接口隔离原则有如下两种定义。
第一种定义:
Clients should not be forced to depend upon inerfaces that they don't use。
意思是:客户端不应该依赖它不需要的接口。
第二种定义:
The dependency of one class to another one should depend on tje smallest possible interface.
意思是:类间的依赖关系应该建立在最小的接口上。
接口隔离原则的具体含义如下。
- 一个类对另外一个类的依赖性应当是建立在最小的接口上的。
- 一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个巨大臃肿的接口,这是对角色和接口的污染。因此使用多个专门的接口比使用单一的总接口要好。
- 不应该强迫客户依赖与他们不用的方法。接口属于客户,不属于它所在的类层次结构,即不要强迫客户使用他们不用的方法,否则这些客户就会面临由于这些不同的使用方法的改变所带来的的改变。
2接口隔离原则的应用
接口隔离原则的应用场合,只提供调用者需要的方法,屏蔽不需要的方法。
如下面的电子商务系统,该系统中有订单这个类,并在三个地方会使用到订单类:
- 一个是门户,只能有查询方法;
- 一个是外部系统,有订单添加的方法;
- 一个是后台管理,添加、删除、修改、查询的都要用到
针对这三个不同的应用场景,为满足接口隔离原则,应使用不同的接口进行隔离,每个接口提供的方法不同,这样使每个应用都建立在最小接口上。
用户门户应用接口 IOrderForPortal.java
package com.eric.设计模式原则.接口隔离原则;
/**
* @author Eric
* @ProjectName my_design_23
* @description 用户门户与订单的接口
* @CreateTime 2020-11-23 17:55:02
*/
//用户门户应用接口
public interface IOrderForPortal {
public String getOrder();
}
外部应用系统接口 IOrderForOtherSys.java
package com.eric.设计模式原则.接口隔离原则;
/**
* @author Eric
* @ProjectName my_design_23
* @description 外部系统与订单接口
* @CreateTime 2020-11-23 17:56:20
*/
//外部系统应用接口
public interface IOrderForOtherSys {
public void insertOrder();
}
管理平台应用接口 IOrderForAdmin.java
package com.eric.设计模式原则.接口隔离原则;
/**
* @author Eric
* @ProjectName my_design_23
* @description 管理平台和订单的接口
* @CreateTime 2020-11-23 17:56:56
*/
//管理平台应用接口
public interface IOrderForAdmin {
public String getOrder();
public void insertOrder();
public void updateOrder();
public void deleteOrder();
}
Order类实现IOrderForPortal、IOrderForOtherSys、IOrderForAdmin
package com.eric.设计模式原则.接口隔离原则;
/**
* @author Eric
* @ProjectName my_design_23
* @description 订单类
* @CreateTime 2020-11-23 17:58:56
*/
public class Order implements IOrderForAdmin,IOrderForOtherSys,IOrderForPortal {
//返回给Portal
public static IOrderForPortal getOrderForPortal(){
return new Order();
}
//返回给OtherSys
public static IOrderForOtherSys getOrderForOtherSys(){
return new Order();
}
//返回给Admin
public static IOrderForAdmin getOrderForAdmin(){
return new Order();
}
public String getOrder() {
return "返回订单";
}
public void insertOrder() {
System.out.println("插入订单");
}
public void updateOrder() {
System.out.println("更新订单");
}
public void deleteOrder() {
System.out.println("删除订单");
}
}
测试:
package com.eric.设计模式原则.接口隔离原则;
/**
* @author Eric
* @ProjectName my_design_23
* @description 某电子商务系统业务的测试类
* @CreateTime 2020-11-23 18:10:10
*/
public class test {
public static void main(String[] args) {
//获取用户门户对应的实例,该对象只能使用getOrder()方法
IOrderForPortal op = Order.getOrderForPortal();
System.out.println(op.getOrder());
//获取外部系统接口对应的实例,该对象只能用insertOrder()方法
IOrderForOtherSys os = Order.getOrderForOtherSys();
os.insertOrder();
//获取管理平台接口对应的实例,该对象可以使用Order类中提供的所有方法
IOrderForAdmin oa = Order.getOrderForAdmin();
System.out.println(oa.getOrder());
oa.insertOrder();
oa.updateOrder();
oa.deleteOrder();
}
}
通过上述代码可以看到,Order类通过IOrderForPortal、IOrderForOtherSys、IOrderForAdmin
这三个接口,可以对不同的用户使用不同的接口进行隔离。
接口隔离原则是对接口的定义,同时是对类的定义,应尽量使用原子接口或原子类,其中''原子'在实践应用中可以根据以下几个规则来衡量:
- 一个接口只对一个子模块或者业务逻辑进行服务;
- 只保留接口中业务逻辑需要的public方法;
- 尽量修改污染了的接口,若修改的风险较大,则可采用适配器模式进行转化处理。
- 接口设计应因项目而异,因环境而异,不能教条照搬。
接口隔离原则和其他的设计原则一样,都是需要花费时间和精力来进行设计和筹划的,但是它带来设计的灵活性,并降低整个项目的风险,当业务变化时能够快速应付。在设计接口时应根据经验和常识决定粒度的大小,如果接口粒度太小,导致接口数量剧增,会给开发带来难度;如果接口粒度太大,灵活性降低,无法提供定制服务,给项目带来无法估计的风险。
只要你不停下来,慢一点也没关系。