概要
Clients should not be forced to depend upon interfaces that they do not use.不能強迫用戶去依賴那些他們不使用的接口。換句話說,使用多個專門的接口比使用單一的總接口總要好。
它包含了2層意思:
- 接口的設(shè)計原則:接口的設(shè)計應(yīng)該遵循最小接口原則,不要把用戶不使用的方法塞進同一個接口里。
如果一個接口的方法沒有被使用到,則說明該接口過胖,應(yīng)該將其分割成幾個功能專一的接口。
- 接口的依賴(繼承)原則:如果一個接口a依賴(繼承)另一個接口b,則接口a相當(dāng)于繼承了接口b的方法,那么繼承了接口b后的接口a也應(yīng)該遵循上述原則:不應(yīng)該包含用戶不使用的方法。
反之,則說明接口a被b給污染了,應(yīng)該重新設(shè)計它們的關(guān)系。
如果用戶被迫依賴他們不使用的接口,當(dāng)接口發(fā)生改變時,他們也不得不跟著改變。換而言之,一個用戶依賴了未使用但被其他用戶使用的接口,當(dāng)其他用戶修改該接口時,依賴該接口的所有用戶都將受到影響。這顯然違反了開閉原則,也不是我們所期望的。
下面我們舉例說明怎么設(shè)計接口或類之間的關(guān)系,使其不違反ISP原則。
假如有一個Door,有l(wèi)ock,unlock功能,另外,可以在Door上安裝一個Alarm而使其具有報警功能。用戶可以選擇一般的Door,也可以選擇具有報警功能的Door。
有以下幾種設(shè)計方法:
ISP原則的違反例:
方法一:
在Door接口里定義所有的方法。圖:
但這樣一來,依賴Door接口的CommonDoor卻不得不實現(xiàn)未使用的alarm()方法。違反了ISP原則。
方法二:
在Alarm接口定義alarm方法,在Door接口定義lock,unlock方法,Door接口繼承Alarm接口。
跟方法一一樣,依賴Door接口的CommonDoor卻不得不實現(xiàn)未使用的alarm()方法。違反了ISP原則。
遵循ISP原則的例:
方法三:通過多重繼承實現(xiàn)
在Alarm接口定義alarm方法,在Door接口定義lock,unlock方法。接口之間無繼承關(guān)系。CommonDoor實現(xiàn)Door接口,
AlarmDoor有2種實現(xiàn)方案:
1),同時實現(xiàn)Door和Alarm接口。
2),繼承CommonDoor,并實現(xiàn)Alarm接口。該方案是繼承方式的Adapter設(shè)計模式的實現(xiàn)。
第2)種方案更具有實用性。
這種設(shè)計遵循了ISP設(shè)計原則。
方法四:通過委讓實現(xiàn)
這種方法其實是委讓方式的Adapter設(shè)計模式的實現(xiàn)。
在這種方法里,AlarmDoor實現(xiàn)了Alarm接口,同時把功能lock和unlock委讓給CommonDoor對象完成。
這種設(shè)計遵循了ISP設(shè)計原則。
小結(jié)
Interface Segregation Principle (ISP)從對接口的使用上為我們對接口抽象的顆粒度建立了判斷基準:在為系統(tǒng)設(shè)計接口的時候,使用多個專門的接口代替單一的胖接口。