接口隔离原则
一:什么是接口?
● 实例接口(Object Interface)
---->Person zhangSan=new Person()产生了一个实例,这个实例要遵从的标准就是Person这个类,Person类就是zhangSan的接口
● 类接口(Class Interface)
---->Java中经常使用的interface关键字定义的接口。
二:那什么是隔离呢?它有两种定义:
---->事物的定义一般都比较难理解,晦涩难懂是正常的。我们把这两个定义剖析一下
---->第一种定义:客户端不应该依赖它不需要的接口”,那依赖什么?依赖它需要的接口,客户端需要什么接口就提供什么接口,把不需要的接口剔除掉,那就需要对接口进行细化,保证其纯洁性.
---->第二种定义:类间的依赖关系应该建立在最小的接口上”,它要求是最小的接口,也是要求接口细化,接口纯洁,与第一个定义如出一辙,只是一个事物的两种不同描述。
---->总结:建立单一接口,不要建立臃肿庞大的接口。再通俗一点讲:接口尽量细化,同时接口中的方法尽量少
---->疑惑点:看到这里大家有可能要疑惑了,这与单一职责原则不是相同的吗?错,接口隔离原则与单一职责的审视角度是不相同的,单一职责要求的是类和接口职责单一,注重的是职责,这是业务逻辑上的划分,而接口隔离原则要求接口的方法尽量少。例如一个接口的职责可能包含10个方法,这10个方法都放在一个接口中,并且提供给多个模块访问,各个模块按照规定的权限来访问,在系统外通过文档约束“不使用的方法不要访问”,按照单一职责原则是允许的,按照接口隔离原则是不允许的,因为它要求“尽量使用多个专门的口”。专门的接口指什么?就是指提供给每个模块的都应该是单一接口,提供给几个模块就应该有几个接口,而不是建立一个庞大的臃肿的接口,容纳所有的客户端访问。
例子:
美女分为脸蛋气质美女和身材美女
一个脸蛋气质的接口
一个身材美女的接口
一个抽象类拥有两个接口的依赖
一个脸蛋气质的接口
package com.yeepay.sxf.sjms1;
/**
* 五官气质美女接口
* @author sxf
*
*/
public interface IGoodBodyGirl {
/**
* 好看的五官外貌
*/
public void goodLooking();
/**
* 有气质
*/
public void greatTemperament();
}
一个身材美女的接口
package com.yeepay.sxf.sjms1;
/**
* 身材美女
* @author sxf
*
*/
public interface IGreatTemperamentGirl{
/**
* 好身材
*/
public void niceFigure();
}
一个抽象类拥有两个接口的依赖
package com.yeepay.sxf.sjms1;
/**
* 星探的抽象类
* @author sxf
*
*/
public abstract class AbstractSearcher2 {
/**
* 脸蛋气质美女
*/
protected IGoodBodyGirl iGoodBodyGirl;
/**
* 脸蛋气质身材美女
*/
protected IGreatTemperamentGirl iGreatTemperamentGirl;
/**
* 脸蛋气质美女
* @param pettyGirl
*/
public AbstractSearcher2(IGoodBodyGirl iGoodBodyGirl){
this.iGoodBodyGirl=iGoodBodyGirl;
}
/**
* 脸蛋气质身材美女
* @param iGreatTemperamentGirl
*/
public AbstractSearcher2(IGreatTemperamentGirl iGreatTemperamentGirl){
this.iGreatTemperamentGirl=iGreatTemperamentGirl;
}
/**
* 搜索美女
*/
public abstract void show();
}
三:如何保证接口的纯洁性
● 接口要尽量小
--->这是接口隔离原则的核心定义,不出现臃肿的接口(Fat Interface),但是“小”是有限度的,首先就是不能违反单一职责原则
--->根据接口隔离原则拆分接口时,首先必须满足单一职责原则
● 接口要高内聚
--->什么是高内聚?高内聚就是提高接口、类、模块的处理能力,减少对外的交互。比如你告诉下属“到奥巴马的办公室偷一个×××文件”,然后听到下属用坚定的口吻回答你:“是,保证完成任务!”一个月后,你的下属还真的把×××文件放到你的办公桌上了,这种不讲任何条件、立刻完成任务的行为就是高内聚的表现。具体到接口隔离原则就是,要求在接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也就越少,同时也有利于降低成本。
● 定制服务
--->一个系统或系统内的模块之间必然会有耦合,有耦合就要有相互访问的接口(并不一定就是Java中定义的Interface,也可能是一个类或单纯的数据交换),我们设计时就需要为各个访问者(即客户端)定制服务,什么是定制服务?定制服务就是单独为一个个体提供优良的服务。我们在做系统设计时也需要考虑对系统之间或模块之间的接口采用定制服务。采用定制服务就必然有一个要求:只提供访问者需要的方法
● 接口设计是有限度的
--->接口的设计粒度越小,系统越灵活,这是不争的事实。但是,灵活的同时也带来了结构的复杂化,开发难度增加,可维护性降低,这不是一个项目或产品所期望看到的,所以接口设计一定要注意适度
四:最佳实践
接口隔离原则是对接口的定义,同时也是对类的定义,接口和类尽量使用原子接口或原子类来组装。但是,这个原子该怎么划分是设计模式中的一大难题,在实践中可以根据以下几个规则来衡量:
● 一个接口只服务于一个子模块或业务逻辑;
● 通过业务逻辑压缩接口中的public方法,接口时常去回顾,尽量让接口达到“满身筋骨肉”,而不是“肥嘟嘟”的一大堆方法;
● 已经被污染了的接口,尽量去修改,若变更的风险较大,则采用适配器模式进行转化处理;
● 了解环境,拒绝盲从。每个项目或产品都有特定的环境因素,别看到大师是这样做的你就照抄。千万别,环境不同,接口拆分的标准就不同。深入了解业务逻辑,最好的接口设计就出自你的手中!