设计模式6大设计原则解读——接口隔离原则

上一篇我们解读了依赖倒置原则,今天来说一下接口隔离原则。

  1. 接口隔离原则(Interface Segregation Principle)
    定义:
    1、客户端不应该依赖它不需要的接口;
    2、一个类对另一个类的依赖应该建立在最小的接口上。
    原文定义:
    1、Clients should not be forced to depend upon interfaces that they don’t use.
    2、The dependency of one class to another one should depend on the smallest possible interface.
    简要解读:在说接口隔离之前,我们先来说一下接口的定义。什么是接口呢?我们在开发中经常会用到interface关键字定义的接口,这确实是一种接口,是类接口(Class Interface)。还有一种接口是实例接口(Object Interface),在java语言中,类是对事物的抽象,使用new关键字可以产生类的实例,是对某类事物的描述,这也是一种接口。比如:定义了Person类,使用Person cai = new Person();产生了一个Person的实例cai,那么cai就要符合Person的特征。我们只需要知道从这个角度来说类也是一种接口就可以了,也不用迷惑,如果不理解,只能说是被java浸染时间太长啦。
    接下来我们来说说第一种定义,实际上就是说客户端应该依赖它需要的接口,不需要的接口就不要依赖了,尽量不提供客户端不需要的接口,实际上就是对接口进行细化,保证接口的纯洁性。第二种定义也是一样强调接口的纯洁性,要求接口尽量小,这只是针对一种事物的两种不同角度的描述而已。概括起来就是说我们提供的接口要尽量精简,创建单一的接口,不用臃肿庞大的接口,同时接口中定义的方法也要尽量少。
    也许你会说接口隔离原则和单一职责原则不是一样的吗?其实不是的,单一职责原则强调的是业务层面的职责单一,是业务逻辑上的划分,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节,而接口隔离原则要求接口的方法尽量少,接口隔离原则注重对接口依赖的隔离。两个原则的审视角度是不同的。例如:一个接口的职责可能包含10个方法,这10个方法都在一个接口中,并且提供给多个模块访问,各个模块按照规定的权限来访问,在系统外通过文档约束不使用的方法不要调用访问,这种情况按照单一职责原则是允许的。但是按照接口隔离原则是不允许的,因为接口隔离原则要求尽量使用多个专门的接口。专门的接口就是说提供给每个模块的接口都应该是单一接口,提供给几个模块访问就应该有几个接口,每个接口中的方法都应该尽量少,不应该提供模块不需要的方法。
    场景再现:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
    解决方案:将臃肿庞大的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。
    理解:
    在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。下面我们通过一个例子来说明接口隔离原则对我们提出的要求。
    大家对美女的评判各有不同,那什么样的才算美女呢?下面我们使用星探寻找美女这个场景来解读接口隔离原则。美女一般需要脸好看,身材好或者气质好等。下面是星探寻找美女的类图:

设计模式6大设计原则解读——接口隔离原则

我们定义了一个抽象类AbstractSearcher和一个接口IPettyGirl,接口里面有三个方法分别是有好的面容,好身材,好气质。这样星探只要按照这个标准就很容易找到符合标准的美女了。美女的实现类代码如下图:

设计模式6大设计原则解读——接口隔离原则

设计模式6大设计原则解读——接口隔离原则

下面是星探的抽象类和实现类代码,如下图:

设计模式6大设计原则解读——接口隔离原则

美女和星探类都准备完毕,那么我们来看场景类中实现星探寻找美女的过程。如下图:

设计模式6大设计原则解读——接口隔离原则

我们的程序运行没有问题,但是我们的设计合理吗?我们看看IPettyGirl这个接口的设计,其实我们可以对其进行优化。随着社会的进步,人类的审美也提高了,于是出现了气质型美女,虽然气质型美女不一定符合我们上面接口定义的那些特征,但是也不可否认气质型美女确实也是美女的一种。那么气质型美女没有实现三个方法那么就不是美女了吗?我们发现上面的程序就会出现问题。也许你会说我新建个类来实现IPettyGirl接口,其他两个方法不去实现不就可以了,但是星探依赖的是IPettyGirl接口,只实现两个方法,星探的方法就要修改了,打出的结果少了两条怎么让星探去辨别了呢,到此我们发现了这个接口的设计问题。接下来我们进行修改,修改后的类图如下:

设计模式6大设计原则解读——接口隔离原则

我们按照接口隔离原则把原来的IPettyGirl接口拆成了两个接口,一种是外形美,一种是气质美,这样设计就变得更加灵活。两种美女定义代码如下:

设计模式6大设计原则解读——接口隔离原则

标准的美女不仅要有外形美,气质素质也要高才算真正的美女,那么真正的美女的实现代码如下图:

设计模式6大设计原则解读——接口隔离原则

接下来我们来说说如何保证接口的纯洁性,主要包含以下四个方面。
接口隔离原则的4层原则

接口要尽量小
这是接口隔离原则最核心的定义,接口要尽量小,但是也是有一定限度的,不能违反单一职责原则,也就是说我们要把握一个限度,在应用接口隔离原则的时候首先要保证符合单一职责原则。不能无限的拆分下去,否则不仅没有达到良好的设计,还会导致类或接口的增多。
接口要高内聚
高内聚就是提高接口、类、模块的处理能力,减少对外的交互。也就是说在接口中尽量少定义public的方法,对外提供的方法越少,风险也就越小。
定制服务(单独为一个个体提供优良的服务)
定制服务就是提供访问者需要的方法,尽量不要在一个接口中提供多个方法供很多模块调用。
接口设计是有限度的(灵活设计接口粒度大小)
接口的设计粒度越小,系统越灵活,但是过度的细化也会带来程序结构的复杂化,增加开发难度和工作量,也会使程序可维护性降低,所以接口设计需要掌握一个限度。

如何更好的应用接口隔离原则呢?需要根据经验和常识去掌握这个限度,以下是可以遵循的几个规则:
1、一个接口只服务于一个子模块或业务逻辑
2、通过业务逻辑压缩接口中的public方法
3、已经被污染了的接口,可以尽量修改,如果变更风险较大的话可以采用设计模式中的适配器模式进行转化处理。(23种设计模式会在后续的博客中进行解读)
4、了解环境,拒绝盲从。不能看到某些接口拆分的设计就去照搬,要深入理解业务逻辑,根据具体场景去进行拆分。
需要说明的是接口隔离原则和其他设计原则一样,都需要花费较多的时间和精力去设计和筹划,但是这些原则提高了设计的灵活性,能在需求漫天飞,无边改的情况下较为容易的处理这些棘手的问题,前期的这些设计也算是物尽其用了。
接口隔离原则就说到这里,下一篇我们将介绍迪米特法则。