3.接口隔离原则(Interface Segregation Principle)(ISP)
定义: 类间的依赖关系应该建立在最小的接口上
接口隔离原则有两个定义:
- `1.客户端不应该依赖它不需要的接口`
- `2. 类间的依赖关系应该建立在最小的接口上`
首先来看**客户端不应该依赖它不需要的接口**,那么意思就是要依赖它需要的接口,把不需要的接口剔除掉,就需要接口细化,如果接口的方法比较杂乱就没办法剔除。
**类间的依赖关系应该建立在最小的依赖关系上**要求接口细化,因为接口细化之后,才能做到嘴小依赖关系。由此可见,接口隔离原则的要求就是一条:**接口细化**
如何做到接口细化?
就是要求尽量减少接口的方法。例如,我们去银行办理业务,银行有存款,取款,转账,理财等业务。每一个窗口有一个业务员,每一个窗口都可以办理这些业务。因此业务员的职责都是一样的。
银行的职责有:存款,取款,转账,理财。
public interface Bank {
/**
* 存款
*/
void saving();
/**
* 取款
*/
void fetch();
/**
* 转账
*/
void transfer();
/**
* 理财
*/
void manageMoney();
}
这样看的话,这个银行接口的设计是符合职责单一原则的,那么业务员的实现就是:
public class BankSalesman implements Bank {
@Override
public void saving() {
System.out.println("存款");
}
@Override
public void fetch() {
System.out.println("取款");
}
@Override
public void transfer() {
System.out.println("转账");
}
@Override
public void manageMoney() {
System.out.println("理财");
}
}
业务员实现了银行的接口,每一个业务员都有存款,取款,转账,理财的方法,也就是说每一个业务员都有这些职责,但是这样的设计并不合理,因为每一个业务员都强制必须有这些方法,如果现在银行新招一个业务员
只需要有存取款的方法,其他方法都不需要。这样就没办法提出Bank中的方法,因此这个Bank接口的设计是不符合接口隔离原则的。如何实现接口细化?
将银行的方法拆分:
public interface Saving {
void saving();
}
public interface Fetch {
void fetch();
}
public interface Transfer {
void transfer();
}
public interface ManageMoney {
void manageMoney();
}
业务员需要有哪儿些工作,就实现哪儿些接口,如有一个业务员只有理财的业务:
public class ManageMoneySalesman implements ManageMoney {
@Override
public void manageMoney() {
System.out.println("理财");
}
}
可以看到,业务员需要哪儿些职责,就继承哪儿个接口并实现方法。
接口隔离原则要求:将一个臃肿的接口拆分为多个独立的接口,通过分散定义多个接口,可以预防未来变更的扩散,提高系统的灵活性和可维护性。
接口隔离原则主要包含一下四层含义:
- `1. 接口尽量小`需要注意的是:**根据接口隔离原则拆分接口时,应该首先满足职责单一原则**
- `2. 接口要高内聚`高内聚就是要提高类,接口,模块的处理能力,减少对外的交互。具体到接口隔离原则就是在接口中尽量少公布public方法,接口的pulic 方法越少对系统的开发越有利,变更的风险也就越小。
- `3. 定制服务`一个系统或系统内的模块之间必然会有耦合,有耦合就要有互相访问的接口,这个接口也可能时类,或者方法。定制服务就是只提供访问者需要的方法。
- `4. 接口设计是有限度的`接口设计粒度越小,系统越灵活,但是,相应的带来的结果就是系统结构变得复杂,维护性降低。
接口隔离原则是对接口的定义,同时也是对类的定义。接口的设计可以根据以下规则来划分:
- `1. 一个接口只服务于一个子模块或者业务逻辑`
- `2. 通过业务逻辑压缩接口中的public方法`
- `3. 已经被污染的接口,尽量去修改,若变更的风险较大,则应使用适配器模式进行转换`
- `4. 根据自己项目的需求,深入分析,进行设计,不要盲目追求接口隔离原则`