- 貫穿設計模式:用一個電商項目詳解設計模式
- 偉山育琪
- 1344字
- 2024-12-28 11:44:54
1.2.2 接口隔離原則
對于接口隔離原則(Interface Segregation Principle,IPS),單從“隔離”這個字眼來說,我們很容易錯誤地理解接口隔離原則。因為接口“隔離”意味著接口“劃分”,那么“劃分”是不是就是指職責劃分?職責劃分是不是就是指上一小節所敘述的“單一職責原則”?
其實,單一職責原則是接口隔離原則的基礎,單一職責原則注重職責的劃分,從職責角度進行類和接口的劃分;在此基礎上,接口隔離原則登場,注重接口使用的“精確性”和“最小化”。如果讀者依然沒有理解兩者的區別和關系,請不要著急,可以繼續往下閱讀,我會以JDK源碼為例,為讀者進行更明確的解釋。接口隔離原則,主要體現在以下兩個方面。
(1)不要使用沒有任何依賴關系的接口。
肯定有讀者會認為這是一句空話,而且這句話還泛著一點傻氣。正常開發過程中,如果不依賴某個接口,肯定是沒有人使用的,但是隨著業務代碼的累加,也難免會出現這樣的問題,即使是JDK中數據結構源碼的作者,也依然在不經意間使用了無須使用的接口。接下來我們對JDK源碼的闡述,純粹從技術角度進行展開。
我們先來看下以下代碼執行邏輯。

當我們執行這個main函數的時候,會收到以下報錯信息。

從以上的報錯信息我們能夠清楚看到,是add方法發生了異常,因為Collections通過emptyList()方法創建的空集合,是不能夠進行元素添加的。可是,當我們跳轉到源碼看EmptyList的類結構時,卻發現了RandomAccess接口的存在,而RandomAccess接口真的不應該出現,它是一個無用的接口實現。

為什么說上邊源碼中的RandomAccess是無用的接口實現呢?大部分讀者可能都知道,RandomAccess接口是一個標志接口(Marker),只要類List集合實現這個接口,就能支持快速隨機訪問。可是當前的EmptyList,從對象的創建到滅亡,都不會有任何元素的添加,沒有元素又何談元素的快速隨機訪問呢?
如果單從接口隔離原則上來講,這個RandomAccess接口,完全沒有存在的必要,這是源碼作者的一個疏忽。當然,此處的RandomAccess的使用,也可能是為了后續對EmptyList對象的擴展,支持元素添加功能,只需要實現父類AbstractList中的add方法即可,那么RandomAccess也就自然有了它的用武之地。
我們繼續分析,這部分源碼首先遵循了單一職責原則,RandomAccess作為快速隨機訪問的標志類,就是一個明確的職責劃分,符合單一職責原則;而接口隔離原則在此處的作用是告訴大家:RandomAccess當用時則用,不當用時勿用。
(2)一個類對另外一個類的依賴性應當是建立在最小的接口上的。
一個接口代表一個角色,不應當將不同的角色都交給一個接口。如果將沒有關系的接口合并在一起,形成一個臃腫的大接口,那并不是一個好的設計,違背了接口隔離原則。我們以JDK的ArrayList源碼設計進行說明,體會接口隔離原則的意義。我們來看以下ArrayList類結構:

從上邊的類結構代碼中能夠很明顯地看到,ArrayList有四種特質:
①集合特質:因為實現了List接口。
②快速隨機訪問:因為實現了RandomAccess接口。
③支持克隆:因為實現了Cloneable接口。
④支持序列化:因為實現了Serializable接口。
這樣的類結構,首先是遵循了單一職責原則,按職責劃分為不同的接口;然后在此基礎上,接口隔離原則登場,細化接口的方法,保持接口的純潔性,在滿足需求的前提下,盡量減少接口的方法,做到專業、精確、最小化接口。
當然,我們平時工作過程中,已經不知不覺中遵循了接口隔離原則,不使用沒有依賴關系的接口、接口細化、剔除無用方法等,都是接口隔離原則很好的實踐。還是那句話,一切都應該以項目實際情況為出發點進行設計,因地制宜才是我們真正需要遵守的原則。