面向?qū)ο笤O(shè)計(jì)原則之接口隔離原則

接口隔離原則定義如下:

接口隔離原則(Interface Segregation Principle, ISP):使用多個(gè)專門(mén)的接口,而不使用單一的總接口,即客戶端不應(yīng)該依賴那些它不需要的接口。

根據(jù)接口隔離原則,當(dāng)一個(gè)接口太大時(shí),我們需要將它分割成一些更細(xì)小的接口,使用該接口的客戶端僅需知道與之相關(guān)的方法即可。

每一個(gè)接口應(yīng)該承擔(dān)一種相對(duì)獨(dú)立的角色,不干不該干的事,該干的事都要干。

這里的“接口”往往有兩種不同的含義:
一種是指一個(gè)類型所具有的方法特征的集合,僅僅是一種邏輯上的抽象;
另外一種是指某種語(yǔ)言具體的“接口”定義,有嚴(yán)格的定義和結(jié)構(gòu),比如Java語(yǔ)言中的interface。
對(duì)于這兩種不同的含義,ISP的表達(dá)方式以及含義都有所不同:

(1) 當(dāng)把“接口”理解成一個(gè)類型所提供的所有方法特征的集合的時(shí)候,這就是一種邏輯上的概念,接口的劃分將直接帶來(lái)類型的劃分??梢园呀涌诶斫獬山巧?,一個(gè)接口只能代表一個(gè)角色,每個(gè)角色都有它特定的一個(gè)接口,此時(shí),這個(gè)原則可以叫做“角色隔離原則”。

(2) 如果把“接口”理解成狹義的特定語(yǔ)言的接口,那么ISP表達(dá)的意思是指接口僅僅提供客戶端需要的行為,客戶端不需要的行為則隱藏起來(lái),應(yīng)當(dāng)為客戶端提供盡可能小的單獨(dú)的接口,而不要提供大的總接口。在面向?qū)ο缶幊陶Z(yǔ)言中,實(shí)現(xiàn)一個(gè)接口就需要實(shí)現(xiàn)該接口中定義的所有方法,因此大的總接口使用起來(lái)不一定很方便,為了使接口的職責(zé)單一,需要將大接口中的方法根據(jù)其職責(zé)不同分別放在不同的小接口中,以確保每個(gè)接口使用起來(lái)都較為方便,并都承擔(dān)某一單一角色。接口應(yīng)該盡量細(xì)化,同時(shí)接口中的方法應(yīng)該盡量少,每個(gè)接口中只包含一個(gè)客戶端(如子模塊或業(yè)務(wù)邏輯類)所需的方法即可,這種機(jī)制也稱為“定制服務(wù)”,即為不同的客戶端提供寬窄不同的接口。

下面通過(guò)一個(gè)簡(jiǎn)單實(shí)例來(lái)加深對(duì)接口隔離原則的理解:

Sunny軟件公司開(kāi)發(fā)人員針對(duì)某CRM系統(tǒng)的客戶數(shù)據(jù)顯示模塊設(shè)計(jì)了如圖1所示接口,其中方法dataRead()用于從文件中讀取數(shù)據(jù),方法transformToXML()用于將數(shù)據(jù)轉(zhuǎn)換成XML格式,方法createChart()用于創(chuàng)建圖表,方法displayChart()用于顯示圖表,方法createReport()用于創(chuàng)建文字報(bào)表,方法displayReport()用于顯示文字報(bào)表。

圖1 初始設(shè)計(jì)方案結(jié)構(gòu)圖.png

在實(shí)際使用過(guò)程中發(fā)現(xiàn)該接口很不靈活,例如如果一個(gè)具體的數(shù)據(jù)顯示類無(wú)須進(jìn)行數(shù)據(jù)轉(zhuǎn)換(源文件本身就是XML格式),但由于實(shí)現(xiàn)了該接口,將不得不實(shí)現(xiàn)其中聲明的transformToXML()方法(至少需要提供一個(gè)空實(shí)現(xiàn));如果需要?jiǎng)?chuàng)建和顯示圖表,除了需實(shí)現(xiàn)與圖表相關(guān)的方法外,還需要實(shí)現(xiàn)創(chuàng)建和顯示文字報(bào)表的方法,否則程序編譯時(shí)將報(bào)錯(cuò)。

現(xiàn)使用接口隔離原則對(duì)其進(jìn)行重構(gòu)。

在圖1中,由于在接口CustomerDataDisplay中定義了太多方法,即該接口承擔(dān)了太多職責(zé),一方面導(dǎo)致該接口的實(shí)現(xiàn)類很龐大,在不同的實(shí)現(xiàn)類中都不得不實(shí)現(xiàn)接口中定義的所有方法,靈活性較差,如果出現(xiàn)大量的空方法,將導(dǎo)致系統(tǒng)中產(chǎn)生大量的無(wú)用代碼,影響代碼質(zhì)量;另一方面由于客戶端針對(duì)大接口編程,將在一定程序上破壞程序的封裝性,客戶端看到了不應(yīng)該看到的方法,沒(méi)有為客戶端定制接口。因此需要將該接口按照接口隔離原則和單一職責(zé)原則進(jìn)行重構(gòu),將其中的一些方法封裝在不同的小接口中,確保每一個(gè)接口使用起來(lái)都較為方便,并都承擔(dān)某一單一角色,每個(gè)接口中只包含一個(gè)客戶端(如模塊或類)所需的方法即可。

通過(guò)使用接口隔離原則,本實(shí)例重構(gòu)后的結(jié)構(gòu)如圖2所示:

圖2 重構(gòu)后的結(jié)構(gòu)圖.png

在使用接口隔離原則時(shí),我們需要注意控制接口的粒度,接口不能太小,如果太小會(huì)導(dǎo)致系統(tǒng)中接口泛濫,不利于維護(hù);接口也不能太大,太大的接口將違背接口隔離原則,靈活性較差,使用起來(lái)很不方便。
一般而言,接口中僅包含為某一類用戶定制的方法即可,不應(yīng)該強(qiáng)迫客戶依賴于那些它們不用的方法。

文章轉(zhuǎn)載自 —— 面向?qū)ο笤O(shè)計(jì)原則之接口隔離原則

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容