在软件开发过程中,如果两个人负责两个不同的模块,那么两个人一般先定义好交互的接口(interface),这样就可以先自己开发自己的模块,然后再进行联调测试。然而,如果说A提供的接口里面包含了过多的内容,有些是B不需要的,那么这个借口就显得很臃肿了,A维护麻烦,B使用也麻烦。这就是我们要说的接口隔离原则。
接口隔离原则:
Clients should not be forced to depend upon interfaces that they don't use.
即:
客户不应该被迫依赖于他们不使用的接口。
接口隔离原则规定客户端不应该被迫实现他们不使用的接口。 代替一个大的(胖的)接口,许多小的(瘦的)接口要更好,讲一个个子模块拆分开。看起来是不是感觉和单一职责原则有些类似,都有强调到按照清晰的职责来拆分。
当然,单一职责更注重类的职责,引起类的变化的原因要有且仅有一个。而接口隔离原则强调要提供足够小的接口。
我们参考下面的例子看一下:
// interface segregation principle - bad example interface IWorker { public void work(); public void eat(); } class Worker implements IWorker{ public void work() { // ....working } public void eat() { // ...... eating in launch break } } class SuperWorker implements IWorker{ public void work() { //.... working much more } public void eat() { //.... eating in launch break } } class Manager { IWorker worker; public void setWorker(IWorker w) { worker=w; } public void manage() { worker.work(); } } |
对于IWorker来说有work和eat,因此Worker也实现了work和eat两个方法,但是对于Manager来说,他值关心work,而不关心eat。所以,对于Manager来说IWorker接口暴露了它不感兴趣,也不需要的方法。
不满足接口隔离原则,因而应该进行拆分:
// interface segregation principle - good example interface IWorker extends Feedable, Workable { } interface IWorkable { public void work(); } interface IFeedable{ public void eat(); } class Worker implements IWorkable, IFeedable{ public void work() { // ....working } public void eat() { //.... eating in launch break } } class Robot implements IWorkable{ public void work() { // ....working } } class SuperWorker implements IWorkable, IFeedable{ public void work() { //.... working much more } public void eat() { //.... eating in launch break } } class Manager { Workable worker; public void setWorker(Workable w) { worker=w; } public void manage() { worker.work(); } } |
这样,拆分后我们可以看到,系统解耦,从而更容易重构、扩展、修改、和重新部署。
最后我们来总结一下:
1、接口应该尽量小,但是要有限度。
2、接口只暴露给依赖接口的类(调用端)需要的方法,而不需要暴露不需要的方法。
3、提高模块的内聚,减少它们之间的耦合。
当然,如果系统已经成型很久,不容易改变,可以运用适配者模式(Adapter pattern)来实现接口隔离原则。
像其他的原则一样,接口隔离原则也是需要在设计、重构过程中需要话费时间来思考如何运用。有时候因为时间紧迫我们可能着急于完成功能,但是当我们不断的进行扩展,添加新功能的时候,会发现,如果不重构,这段代码将越来越难重构,以至于拖累项目运转。当然,我们也不可过度设计。
参考:
http://blog.csdn.net/moxiaoya1314/article/details/51899048
https://en.wikipedia.org/wiki/Interface_segregation_principle