動機
當(dāng)我們設(shè)計應(yīng)用程序的時候,如果一個模塊包含多個子模塊,那么我們應(yīng)該小心對該模塊做出抽象。設(shè)想該模塊由一個類實現(xiàn),我們可以把系統(tǒng)抽象成一個接口。但是當(dāng)我們想要添加一個新的模塊擴展程序時,如果要添加的模塊只包含原系統(tǒng)中的一些子模塊,那么就會強迫我們實現(xiàn)接口中的所有方法,并且還要編寫一些啞方法。這樣的接口被稱為胖接口或者叫被污染的接口,使用這樣的接口將會給系統(tǒng)引入一些不正確的行為。
接口隔離原則表明客戶端不應(yīng)該被強迫實現(xiàn)一些他們不會使用的接口,應(yīng)該把胖接口中的方法分組,然后用多個接口代替它,每個接口服務(wù)于一個子模塊。
接口隔離原則
不應(yīng)該強迫客戶端依賴于他們不會使用的接口。
實例
下面是一個違反了接口隔離原則的例子。我們使用Manager類代表一個管理工人的管理者。有兩種類型的工人:普通的和高效的,這兩種工人都需要吃午飯?,F(xiàn)在來了一批機器人,它們同樣為公司工作,但是他們不需要吃午飯。一方面Robot類需要實現(xiàn)IWoker接口,因為他們要工作,另一方面,它們又不需要實現(xiàn)IWorker接口,因為它們不需要吃飯。
在這種情況下IWorker就被認(rèn)為是一個被污染了的接口。
如果我們保持現(xiàn)在的設(shè)計,那么Robot類將被迫實現(xiàn)eat()方法,我們可以寫一個啞類它什么也不做(比如說它只用一秒鐘的時間吃午飯),但是這會對程序造成不可預(yù)料的結(jié)果(例如管理者看到的報表中顯示被帶走的午餐多于實際的人數(shù))。
根據(jù)接口隔離原則,一個靈活的設(shè)計不應(yīng)該包含被污染的接口。對于我們的例子來說,我們應(yīng)該把IWorker分離成2個接口。
// interface segregation principle - bad exampleinterface 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分離成兩個接口,Robot類不需要再被強迫實現(xiàn)eat()方法。如果我們需要為Robot類添加其他的功能,例如重新充電,我們可以創(chuàng)建一個新的IRechargeable接口,其中包含一個重新充電的方法recharge。
//interface segregation principle - good exampleinterface 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 SuperWorker implements IWorkable, IFeedable{public void work() {//.... working much more}public void eat() {//.... eating in launch break}}class Robot implements IWorkable{public void work() {// ....working}}class Manager {IWorkable worker;public void setWorker(IWorkable w) {worker = w;}public void manage() {worker.work();}}
總結(jié)
如果已經(jīng)設(shè)計成了胖接口,可以使用適配器模式隔離它。
像其他設(shè)計原則一樣,接口隔離原則需要額外的時間和努力,并且會增加代碼的復(fù)雜性,但是可以產(chǎn)生更靈活的設(shè)計。如果我們過度的使用它將會產(chǎn)生大量的包含單一方法的接口,所以需要根據(jù)經(jīng)驗并且識別出那些將來需要擴展的代碼來使用它。