官术网_书友最值得收藏!

4.3 保證接口的純潔性

接口隔離原則是對(duì)接口進(jìn)行規(guī)范約束,其包含以下4層含義:

?接口要盡量小

這是接口隔離原則的核心定義,不出現(xiàn)臃腫的接口(Fat Interface),但是“小”是有限度的,首先就是不能違反單一職責(zé)原則,什么意思呢?我們?cè)趩我宦氊?zé)原則中提到一個(gè)IPhone的例子,在這里,我們使用單一職責(zé)原則把兩個(gè)職責(zé)分解到兩個(gè)接口中,類圖如圖4-3所示。

圖4-3 電話類圖

仔細(xì)分析一下IConnectionManager接口是否還可以再繼續(xù)拆分下去,掛電話有兩種方式:一種是正常的電話掛斷,一種是電話異常掛機(jī),比如突然沒(méi)電了,通訊當(dāng)然就斷了。這兩種方式的處理應(yīng)該是不同的,為什么呢?正常掛電話,對(duì)方接受到掛機(jī)信號(hào),計(jì)費(fèi)系統(tǒng)也就停止計(jì)費(fèi)了,那手機(jī)沒(méi)電了這種方式就不同了,它是信號(hào)丟失了,中繼服務(wù)器檢查到了,然后通知計(jì)費(fèi)系統(tǒng)停止計(jì)費(fèi),否則你的費(fèi)用不是要瘋狂地增長(zhǎng)了嗎?

思考到這里,我們是不是就要?jiǎng)邮职袸ConnectionManager接口拆封成兩個(gè),一個(gè)接口是負(fù)責(zé)連接,一個(gè)接口是負(fù)責(zé)掛電話?是要這樣做嗎?且慢,讓我們?cè)偎伎家幌拢绻鸱至耍蔷筒环蠁我宦氊?zé)原則了,因?yàn)閺臉I(yè)務(wù)邏輯上來(lái)講,通訊的建立和關(guān)閉已經(jīng)是最小的業(yè)務(wù)單位了,再細(xì)分下去就是對(duì)業(yè)務(wù)或是協(xié)議(其他業(yè)務(wù)邏輯)的拆分了。想想看,一個(gè)電話要關(guān)心3G協(xié)議,要考慮中繼服務(wù)器,等等,這個(gè)電話還怎么設(shè)計(jì)得出來(lái)呢?從業(yè)務(wù)層次來(lái)看,這樣的設(shè)計(jì)就是一個(gè)失敗的設(shè)計(jì)。一個(gè)原則要拆,一個(gè)原則又不要拆,那該怎么辦?好辦,根據(jù)接口隔離原則拆分接口時(shí),首先必須滿足單一職責(zé)原則。

?接口要高內(nèi)聚

什么是高內(nèi)聚?高內(nèi)聚就是提高接口、類、模塊的處理能力,減少對(duì)外的交互。比如你告訴下屬“到奧巴馬的辦公室偷一個(gè)XXX文件”,然后聽(tīng)到下屬用堅(jiān)定的口吻回答你:“是,保證完成任務(wù)!”一個(gè)月后,你的下屬還真的把XXX文件放到你的辦公桌上了,這種不講任何條件、立刻完成任務(wù)的行為就是高內(nèi)聚的表現(xiàn)。具體到接口隔離原則就是,要求在接口中盡量少公布public方法,接口是對(duì)外的承諾,承諾越少對(duì)系統(tǒng)的開(kāi)發(fā)越有利,變更的風(fēng)險(xiǎn)也就越少,同時(shí)也有利于降低成本。

?定制服務(wù)

一個(gè)系統(tǒng)或系統(tǒng)內(nèi)的模塊之間必然會(huì)有耦合,有耦合就要有相互訪問(wèn)的接口(并不一定就是Java中定義的Interface,也可能是一個(gè)類或單純的數(shù)據(jù)交換),我們?cè)O(shè)計(jì)時(shí)就需要為各個(gè)訪問(wèn)者(即客戶端)定制服務(wù),什么是定制服務(wù)?定制服務(wù)就是單獨(dú)為一個(gè)個(gè)體提供優(yōu)良的服務(wù)。我們?cè)谧鱿到y(tǒng)設(shè)計(jì)時(shí)也需要考慮對(duì)系統(tǒng)之間或模塊之間的接口采用定制服務(wù)。采用定制服務(wù)就必然有一個(gè)要求:只提供訪問(wèn)者需要的方法,這是什么意思?我們舉個(gè)例子來(lái)說(shuō)明,比如我們開(kāi)發(fā)了一個(gè)圖書管理系統(tǒng),其中有一個(gè)查詢接口,方便管理員查詢圖書,其類圖如圖4-4所示。

圖4-4 圖書查詢類圖

在接口中定義了多個(gè)查詢方法,分別可以按照作者、標(biāo)題、出版社、分類進(jìn)行查詢,最后還提供了混合查詢方式。程序?qū)懞昧耍懂a(chǎn)上線了,突然有一天發(fā)現(xiàn)系統(tǒng)速度非常慢,然后就開(kāi)始痛苦地分析,最終發(fā)現(xiàn)是訪問(wèn)接口中的complexSearch(Map map)方法并發(fā)量太大,導(dǎo)致應(yīng)用服務(wù)器性能下降,然后繼續(xù)跟蹤下去發(fā)現(xiàn)這些查詢都是從公網(wǎng)上發(fā)起的,進(jìn)一步分析,找到問(wèn)題:提供給公網(wǎng)(公網(wǎng)項(xiàng)目是另外一個(gè)項(xiàng)目組開(kāi)發(fā)的)的查詢接口和提供給系統(tǒng)內(nèi)管理人員的接口是相同的,都是IBookSearcher接口,但是權(quán)限不同,系統(tǒng)管理人員可以通過(guò)接口的complexSearch方法查詢到所有的書籍,而公網(wǎng)的這個(gè)方法是被限制的,不返回任何值,在設(shè)計(jì)時(shí)通過(guò)口頭約束,這個(gè)方法是不可被調(diào)用的,但是由于公網(wǎng)項(xiàng)目組的疏忽,這個(gè)方法還是公布了出去,雖然不能返回結(jié)果,但是還是引起了應(yīng)用服務(wù)器的性能巨慢的情況發(fā)生,這就是一個(gè)臃腫接口引起性能故障的案例。

問(wèn)題找到了,就需要把這個(gè)接口進(jìn)行重構(gòu),將IBookSearcher拆分為兩個(gè)接口,分別為兩個(gè)模塊提供定制服務(wù),修改后的類圖如圖4-5所示。

圖4-5 修改后的圖書查詢類圖

提供給管理人員的實(shí)現(xiàn)類同時(shí)實(shí)現(xiàn)了ISimpleBookSearcher和IComplexBookSearcher兩個(gè)接口,原有程序不用做任何改變,而提供給公網(wǎng)的接口變?yōu)镮SimpleBookSearcher,只允許進(jìn)行簡(jiǎn)單的查詢,單獨(dú)為其定制服務(wù),減少可能引起的風(fēng)險(xiǎn)。

?接口設(shè)計(jì)是有限度的

接口的設(shè)計(jì)粒度越小,系統(tǒng)越靈活,這是不爭(zhēng)的事實(shí)。但是,靈活的同時(shí)也帶來(lái)了結(jié)構(gòu)的復(fù)雜化,開(kāi)發(fā)難度增加,可維護(hù)性降低,這不是一個(gè)項(xiàng)目或產(chǎn)品所期望看到的,所以接口設(shè)計(jì)一定要注意適度,這個(gè)“度”如何來(lái)判斷呢?根據(jù)經(jīng)驗(yàn)和常識(shí)判斷,沒(méi)有一個(gè)固化或可測(cè)量的標(biāo)準(zhǔn)。

主站蜘蛛池模板: 金山区| 鹤庆县| 萨迦县| 玛曲县| 和平县| 延边| 怀集县| 皮山县| 兴化市| 天等县| 泾阳县| 故城县| 普兰店市| 广饶县| 宜城市| 始兴县| 巫山县| 太保市| 麻阳| 青铜峡市| 海淀区| 宁城县| 永安市| 林州市| 交口县| 夏河县| 安化县| 临邑县| 扶沟县| 白城市| 伽师县| 南皮县| 元阳县| 沾益县| 招远市| 沂水县| 朝阳市| 陇川县| 金坛市| 鄯善县| 通河县|