單一職責原則傾向於設計視角,接口分離原則傾向於實現視角,兩者看起來很是類似,可是在某些方面仍是有所區別的。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 原則麼?