界说:客户端不应该依靠它不需求的接口;一个类对另一个类的依靠应该树立在最小的接口上。
问题由来:类A经过接口I依靠类B,类C经过接口I依靠类D,假如接口I关于类A和类B来说不是最小接口,则类B和类D有必要去完结他们不需求的办法。
解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C别离与他们需求的接口树立依靠联系。也便是选用接口阻隔准则。
举例来说明接口阻隔准则:
(图1 未遵从接口阻隔准则的规划)
这个图的意思是:类A依靠接口I中的办法1、办法2、办法3,类B是对类A依靠的完结。类C依靠接口I中的办法1、办法4、办法5,类D是对类C依靠的完结。关于类B和类D来说,尽管他们都存在着用不到的办法(也便是图中赤色字体符号的办法),但因为完结了接口I,所以也有必要要完结这些用不到的办法。对类图不熟悉的能够参照程序代码来了解,代码如下:
interface I {
public void method1();
public void method2();
public void method3();
public void method4();
public void method5();
}
class A{
public void depend1(I i){
i.method1();
}
public void depend2(I i){
i.method2();
}
public void depend3(I i){
i.method3();
}
}
class B implements I{
public void method1() {
System.out.println(“类B完结接口I的办法1”);
}
public void method2() {
System.out.println(“类B完结接口I的办法2”);
}
public void method3() {
System.out.println(“类B完结接口I的办法3”);
}
//关于类B来说,method4和method5不是必需的,可是因为接口A中有这两个办法,
//所以在完结过程中即便这两个办法的办法体为空,也要将这两个没有效果的办法进行完结。
public void method4() {}
public void method5() {}
}
class C{
public void depend1(I i){
i.method1();
}
public void depend2(I i){
i.method4();
}
public void depend3(I i){
i.method5();
}
}
class D implements I{
public void method1() {
System.out.println(“类D完结接口I的办法1”);
}
//关于类D来说,method2和method3不是必需的,可是因为接口A中有这两个办法,
//所以在完结过程中即便这两个办法的办法体为空,也要将这两个没有效果的办法进行完结。
public void method2() {}
public void method3() {}
public void method4() {
System.out.println(“类D完结接口I的办法4”);
}
public void method5() {
System.out.println(“类D完结接口I的办法5”);
}
}
public class Client{
public static void main(String[] args){
A a = new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
C c = new C();
c.depend1(new D());
c.depend2(new D());
c.depend3(new D());
}
}
能够看到,假如接口过于臃肿,只需接口中呈现的办法,不论对依靠于它的类有没有用途,完结类中都有必要去完结这些办法,这明显不是好的规划。假如将这个规划修改为契合接口阻隔准则,就有必要对接口I进行拆分。在这儿咱们将原有的接口I拆分为三个接口,拆分后的规划如图2所示:
(图2 遵从接口阻隔准则的规划)
按例贴出程序的代码,供不熟悉类图的朋友参阅:
interface I1 {
public void method1();
}
interface I2 {
public void method2();
public void method3();
}
interface I3 {
public void method4();
public void method5();
}
class A{
public void depend1(I1 i){
i.method1();
}
public void depend2(I2 i){
i.method2();
}
public void depend3(I2 i){
i.method3();
}
}
class B implements I1, I2{
public void method1() {
System.out.println(“类B完结接口I1的办法1”);
}
public void method2() {
System.out.println(“类B完结接口I2的办法2”);
}
public void method3() {
System.out.println(“类B完结接口I2的办法3”);
}
}
class C{
public void depend1(I1 i){
i.method1();
}
public void depend2(I3 i){
i.method4();
}
public void depend3(I3 i){
i.method5();
}
}
class D implements I1, I3{
public void method1() {
System.out.println(“类D完结接口I1的办法1”);
}
public void method4() {
System.out.println(“类D完结接口I3的办法4”);
}
public void method5() {
System.out.println(“类D完结接口I3的办法5”);
}
}
接口阻隔准则的意义是:树立单一接口,不要树立巨大臃肿的接口,尽量细化接口,接口中的办法尽量少。也便是说,咱们要为各个类树立专用的接口,而不要企图去树立一个很巨大的接口供一切依靠它的类去调用。本文比如中,将一个巨大的接口改变为3个专用的接口所选用的便是接口阻隔准则。在程序规划中,依靠几个专用的接口要比依靠一个归纳的接口更灵敏。接口是规划时对外部设定的“契约”,经过涣散界说多个接口,能够防备外来改变的分散,进步体系的灵敏性和可维护性。
提到这儿,很多人会觉的接口阻隔准则跟之前的单一责任准则很类似,其实不然。其一,单一责任准则原重视的是责任;而接口阻隔准则重视对接口依靠的阻隔。其二,单一责任准则首要是束缚类,其次才是接口和办法,它针对的是程序中的完结和细节;而接口阻隔准则首要束缚接口接口,首要针对笼统,针对程序全体结构的构建。
选用接口阻隔准则对接口进行束缚时,要注意以下几点:
* 接口尽量小,可是要有极限。对接口进行细化能够进步程序规划灵敏性是不挣的现实,可是假如过小,则会形成接口数量过多,使规划复杂化。所以一定要适度。
* 为依靠接口的类定制服务,只露出给调用的类它需求的办法,它不需求的办规律躲藏起来。只要专心地为一个模块供给定制服务,才干树立最小的依靠联系。
* 进步内聚,削减对外交互。使接口用最少的办法去完结最多的工作。
运用接口阻隔准则,一定要适度,接口规划的过大或过小都不好。规划接口的时分,只要多花些时刻去考虑和谋划,才干精确地实践这一准则。