单一职责原则倾向于设计视角,接口分离原则倾向于实现视角,两者看起来很是类似,可是在某些方面仍是有所区别的。java
接口分离原则(Interface Segregation Principle):使用方不该该依赖于它不使用的方法(no client should be forced to depend on methods it does not use.)。ide
ISP 原则是用来处理胖接口或胖基类的,接口或类中包含了茫茫多的方法就称为胖接口或胖基类(简称小胖吧)。使用方在使用小胖的时候,会发现本身没有必要实现某个方法,但因为在小胖中存在,本身不得不实现一个,要么是空方法,要么抛出异常以代表本身不支持。网站
这时候就须要 ISP 原则出场了,它指导你将接口划分红更小的粒度,使用方只须要实现本身须要的接口便可,而不用继承小胖致使不得不实现小胖交代下来的任务。编码
在设计原则只里氏替换原则中,咱们举的例子就违反了接口分离原则,这里再举一个例子说明这个原则。设计
需求要求咱们作一个二手书设计,要求咱们记录书的基本信息,收购的基本信息,以及二手书的鉴定信息等信息。code
设计的接口以下:继承
public interface Book { public String isbn(); public String author(); public Date publishDate(); public PublisherInfo publisher(); public PurchaseInfo purchaseInfo(); public IdentificationInfo identificationInfo(); }
接口工做良好,很好的支持了网站的运行。但因为业务的变化,网站如今不单单要卖二手书了,还要卖新书。这时只是缺乏了收购信息和鉴定信息,可是新书本质上仍是书,所以咱们直接实现了 Book
接口来卖新书。接口
public abstract class NewBook implements Book { public PurchaseInfo purchaseInfo() { return null; } public IdentificationInfo identificationInfo() { return null; } }
全部的新书都使用 NewBook
接口,改动也很小就支持了新书的销售,很美好。ip
这个设计就违反了 ISP 原则,Book
强制全部的书都必须有收购信息和鉴定信息,但新书却并无这两项,将新书实现 Book
接口强制新书也必需要有这两项信息,无奈只能使用折中办法返回null。ci
要改变这种状况,咱们须要将收购信息和鉴定信息单独拆到一个接口中,二手书的实现继承这个接口,而新书的实现不继承这两个接口。
public interface Book { public String isbn(); public String author(); public Date publishDate(); public PublisherInfo publisher(); public PurchaseInfo purchaseInfo(); public IdentificationInfo identificationInfo(); } public interface SecondHand { public PurchaseInfo purchaseInfo(); public IdentificationInfo identificationInfo(); }
接口拆分红这样已经知足网站的要求了,若是后面网站发展愈来愈大,鉴定成本不可承受时,有些书籍不做鉴定直接入库,这时咱们就须要将 SecondHand
接口再拆分红两个接口,将收购信息和鉴定信息分离开来,不做耦和。
SRP 原则说的是一个类只能有一个改变的理由,ISP 原则指的是使用方不该该依赖它不使用的方法。有的设计符合 SRP 原则却并不符合 ISP 原则。
举一个例子,正常的 Stack
都有 push
pop
方法,若是使用方有一个使用场景,只能使用 push
, 不能使用 pop
, 那么使用方就不能继承 Stack
来实现本身的功能,与 ISP 原则相悖。可是原始的 Stack
设计是彻底符合 SRP 原则的,push
与 pop
就是它本身的职责。
从这个例子能够看出,ISP 原则不单单能指导咱们分离接口,还能帮助判断一个类的继承是否是合理的。
可能有的人以为这个例子牵强,谁会限制一个 Stack
不能有 pop
方法。你们能够去看下Java 中的 Stack
实现,它继承了Vector
,而 Vector
是一个 List
, Stack
应该只能压入弹出的,可是却继承了 List
的 add
,remove
,get
等方法,是一个很糟糕的实现设计。
接口分离原则与单一职责原则挺相近,但在某些点上是有区别的。平常编码实现某个接口、继承某个类时,问问本身,这样符合 ISP 原则么?