設計模式原則(4)接口隔離原則

定義

先來明確一下接口的概念,這裏分爲兩種接
1、實例接口
實例化一個類對象後,對應的類就是關於這個對象的接口
2、類接口
Java中利用interface關鍵字定義的接口

接口隔離原則(ISP, Interface Segregation Principle)有兩層定義
1、Clients should not be forced to depend upon interface that they don’t use.(客戶端不應該依賴它不需要的接口)
2、The dependency of one class to another one should depend on the smallest possible interface.(類間依賴應儘可能的建立在最小的接口上)
簡單理解爲:接口中的方法儘量少,能細化則細化。
注意這裏和SRP是不一樣的,他們的度量角度不同,一個是業務角度;一個是方法數量的角度。

示例

秦小波老師在這裏舉了“美女”的例子來說明這麼一個原則。
美女的標準是什麼?面容姣好、魔鬼身材、氣質出衆?三者都要了!
那可能會有一個接口包含三個方法,如下:

interface IBeauty{
     //好面容
     public void goodLooking();
     //好身材
     public void niceFigure();
     //好氣質
     public void greatTemperament();
}

那問題來了,每個人判斷美女的標準是不一樣的。可能有的人面容一般、身材一般,但氣質出衆,這也能被稱之爲美女呢。假設我們還有星探類。那在代碼中又如何實現呢?接口已經限定美女的判斷維度了,再寫個美女類對接口對應方法進行重寫?那好像也不太好,這是不是會影響星探類的代碼呢?
我們發現,在上述例子中,美女的判斷維度分爲了兩層,一個內在(氣質),一個是外在(面容、身材)。那我們是不是可以針對這兩層維度進行一個接口細分設計呢?就比如說我們現在將原有的接口拆分爲兩個接口:一個提供身材和容貌的判斷,一個提供氣質的判斷。

interface IFitBody{
     //好面容
     public void goodLooking();
     //好身材
     public void niceFigure();
}
interface ITemperament{
     //好氣質
     public void greatTemperament();
}

這樣在進行不同標準進行判斷類實現時就可以按需實現不同的接口了。

思考
其實這裏涉及到一個問題。爲什麼不將這裏的外在接口進一步細化爲面容判斷、身材判斷兩個粒度更小的接口呢?這樣對於後期的擴展性不是會更好嗎?首先我們要知道接口隔離的前提是基於單一職責,同時我們要知道接口的細化是要根據實際業務需求去進行粒度把握的,如果無限度的考慮後期的擴展性,導致接口數量的暴漲,對於項目的開發也是災難!

接口隔離也就是保證接口的純潔性,有如下幾條可行原則。

1、接口要儘可能的小
過於複雜的接口會帶來臃腫的設計,而定義粒度過小又會導致接口數量的不必要增加,進而增大了項目開發的難度。那怎麼做呢?注意在進行接口細分時,首先必須要遵循單一職責原則。如此可以更好的把握接口拆分的粒度。

2、接口要高內聚
提高接口、類、模塊的處理能力,減少對外的交互。也就是對於接口使用者來說,並不需要關注接口下對應的具體實現。在此情況下,需要儘量減少對外開放(public),接口是對外開放的承諾;就像是前面說的契約。對外開放的方法越多意味着要給用戶做更多的承諾,帶來的變更風險就會越大。

3、定製服務
針對不同權限的用戶儘量分別定製接口,不要混用。就比如說在web運用中,後臺管理員查詢書籍信息的接口以及公網用戶查詢書籍信息接口是需要分開的,尤其在高併發查詢的情況下,分別定製接口可以避免公網流量影響到內部的正常運作。

4、接口設計是有限度的
這個原則和第一條可以說是交相呼應。接口的設計粒度越小,系統也就越靈活。而這也無疑增大了系統的複雜度,增加了開發維護的成本。如何把握接口設計的純潔性與系統複雜度之間的平衡需要在實踐中進行探索,根據實際的情況綜合考慮。

最佳實踐

1、一個接口只服務於一個子模塊或業務邏輯

2、注意public方法數量的限制;提供了太多對外的公共服務並非好事

3、已被污染的接口儘量去修改,若變更風險太大可採用適配器模式進行轉換處理

4、根據自己實際的業務場景靈活設計自己的模式結構,拒絕照搬盲從。

參考文獻
秦小波《設計模式之禪 》第二版

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章