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

2.6 依賴倒置原則

2.6.1 依賴倒置原則定義

依賴倒置原則是Robert C.Martin于1996年在C++Report上發(fā)表的文章中提出的。

依賴倒置原則(Dependence Inversion Principle,DIP)是指在設(shè)計代碼架構(gòu)時,高層模塊不應(yīng)該依賴于底層模塊,二者都應(yīng)該依賴于抽象。抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。

依賴倒置原則是實現(xiàn)開閉原則的重要途徑之一,它降低了類之間的耦合,提高了系統(tǒng)的穩(wěn)定性和可維護性,同時這樣的代碼一般更易讀,且便于傳承。

2.6.2 模擬場景

在互聯(lián)網(wǎng)的營銷活動中,經(jīng)常為了拉新和促活,會做一些抽獎活動。這些抽獎活動的規(guī)則會隨著業(yè)務(wù)的不斷發(fā)展而調(diào)整,如隨機抽獎、權(quán)重抽獎等。其中,權(quán)重是指用戶在當(dāng)前系統(tǒng)中的一個綜合排名,比如活躍度、貢獻度等。

下面模擬出抽獎的一個系統(tǒng)服務(wù),如果是初次搭建這樣的系統(tǒng)會怎么實現(xiàn)?這個系統(tǒng)是否有良好的擴展性和可維護性,同時在變動和新增業(yè)務(wù)時測試的復(fù)雜度是否高?這些都是在系統(tǒng)服務(wù)設(shè)計時需要考慮的問題。

2.6.3 違背原則方案

下面先用最直接的方式,即按照不同的抽獎邏輯定義出不同的接口,讓外部的服務(wù)調(diào)用。

1.定義抽獎用戶類

這個類就是一個普通的對象類,其中包括了用戶姓名和對應(yīng)的權(quán)重,方便滿足不同的抽獎方式。

接下來實現(xiàn)兩種不同的抽獎邏輯,在一個類中用兩個接口實現(xiàn),如下所示。

在這個抽獎邏輯類中包括了兩個接口,一個是隨機抽獎,另一個是按照權(quán)重排序。

·隨機抽取好理解,把集合中的元素使用工具包Collections.shuffle()進行亂序,之后選取三個元素。當(dāng)然,除了這樣的隨機抽取方式,還有其他方式。

·按照權(quán)重排序,這里使用了list.sort的方法,并按排序邏輯的方式進行自定義排序。最終選擇權(quán)重最高的前三名作為中獎用戶。

2.測試結(jié)果

這里使用單元測試的方式,在初始化數(shù)據(jù)后分別調(diào)用兩個接口方法進行測試。測試結(jié)果如下所示。

從測試結(jié)果上看,程序沒有問題,驗證結(jié)果正常。但是這樣實現(xiàn)有什么問題呢?

如果程序是一次性的、幾乎不變的,那么可以不考慮很多的擴展性和可維護性因素;但如果這些程序具有不確定性,或者當(dāng)業(yè)務(wù)發(fā)展時需要不斷地調(diào)整和新增,那么這樣的實現(xiàn)方式就很不友好了。

首先,這樣的實現(xiàn)方式擴展起來很麻煩,每次擴展都需要新增接口,同時對于調(diào)用方來說需要新增調(diào)用接口的代碼。其次,對于這個服務(wù)類來說,隨著接口數(shù)量的增加,代碼行數(shù)會不斷地暴增,最后難以維護。

2.6.4 依賴倒置原則改善代碼

既然上述方式不具備良好的擴展性,那么用依賴倒置、面向抽象編程的方式實現(xiàn)。

首先定義抽獎功能的接口,任何一個實現(xiàn)方都可以實現(xiàn)自己的抽獎邏輯。

1.抽獎接口

這里只有一個抽獎接口,接口中包括了需要傳輸?shù)?list 集合,以及中獎用戶數(shù)量。

2.隨機抽獎實現(xiàn)

這部分隨機抽獎邏輯與上面的抽獎方式邏輯是一樣的,只不過放到接口實現(xiàn)中了。

3.權(quán)重抽獎實現(xiàn)

權(quán)重抽獎也是一樣,把這些都放到自己的接口實現(xiàn)中。這樣一來,任何一種抽獎都有自己的實現(xiàn)類,既可以不斷地完善,也可以新增。

4.創(chuàng)建抽獎服務(wù)

在這個類中體現(xiàn)了依賴倒置的重要性,可以把任何一種抽獎邏輯傳遞給這個類。這樣實現(xiàn)的好處是可以不斷地擴展,但是不需要在外部新增調(diào)用接口,降低了一套代碼的維護成本,并提高了可擴展性及可維護性。

另外,這里的重點是把實現(xiàn)邏輯的接口作為參數(shù)傳遞,在一些框架源碼中經(jīng)常會有這種做法。

5.測試結(jié)果

這里與前面代碼唯一不同的是新增了實現(xiàn)抽獎的入?yún)?new DrawRandom()、new DrawWeightRank()。在這兩個抽獎的功能邏輯作為入?yún)⒑螅瑪U展起來會非常的方便。

以這種抽象接口為基準(zhǔn)搭建起來的框架結(jié)構(gòu)會更加穩(wěn)定,算程[1]已經(jīng)建設(shè)好,外部只需要實現(xiàn)自己的算子[2]即可,最終把算子交給算程處理。


[1] 算程是一段算法的執(zhí)行過程。

[2] 算子是具體算法的執(zhí)行邏輯。

主站蜘蛛池模板: 大竹县| 乌鲁木齐县| 香港| 西畴县| 伊吾县| 宜兰县| 石渠县| 龙海市| 基隆市| 灌阳县| 阿鲁科尔沁旗| 吉木萨尔县| 安龙县| 资源县| 张家口市| 富顺县| 清原| 玛曲县| 南丰县| 措勤县| 含山县| 潼南县| 当阳市| 枝江市| 晋江市| 汶川县| 黄冈市| 大英县| 佛山市| 东乡族自治县| 平阴县| 基隆市| 清远市| 德安县| 武穴市| 临西县| 冷水江市| 泰和县| 苗栗县| 晋城| 梅河口市|