Resolver: Injection Strategies

Resolver: Injection Strategies翻譯

注入策略

使用 Resolver 執(zhí)行依賴項(xiàng)注入的主要方法有五種:

  1. 接口注入
  2. 屬性注入
  3. 構(gòu)造器注入
  4. 方法注入
  5. 服務(wù)定位器
  6. 注釋 (NEW)

名稱和數(shù)量都來(lái)自于依賴反轉(zhuǎn)绎谦,有關(guān)更深入的討論屎开,請(qǐng)參考 Martin Fowler.

Here I'll simply provide a brief description and an example of implementing each using Resolver.
在這里赡若,我將簡(jiǎn)單地描述下每種策略顿仇,并提供 Resolver 實(shí)現(xiàn)對(duì)應(yīng)策略的例子秤茅。

1. 接口注入

定義

第一種注入技術(shù)是為注入定義一個(gè)接口璧亚,并使用Swift擴(kuò)展將該接口注入到類或?qū)ο笾小?/p>

類:
class XYZViewModel {

    lazy var fetcher: XYZFetching = getFetcher()
    lazy var service: XYZService = getService()

    func load() -> Data {
        return fetcher.getData(service)
    }

}
依賴注入的代碼:
extension XYZViewModel: Resolving {
    func getFetcher() -> XYZFetching { return resolver.resolve() }
    func getService() -> XYZService { return resolver.resolve() }
}

func setupMyRegistrations {
    register { XYZFetcher() as XYZFetching }
    register { XYZService() }
}

請(qǐng)注意砰识,仍需要在getFetcher() 和getService() 中調(diào)用resolve()谴供,否則您將返回到緊密耦合依賴類并繞過解析注冊(cè)系統(tǒng)块茁。

優(yōu)點(diǎn):
  • 輕盈。
  • 對(duì)類隱藏依賴注入系統(tǒng)桂肌。
  • 對(duì)于在初始化過程中沒有訪問權(quán)限的類数焊,如UIViewController,非常有用崎场。
缺點(diǎn):
  • 為每個(gè)需要注入的服務(wù)編寫訪問器函數(shù)佩耳。

2. 屬性注入

定義

屬性注入將其依賴項(xiàng)公開為屬性,依賴項(xiàng)注入系統(tǒng)需要確保在調(diào)用任何方法之前都已設(shè)置好谭跨。

類:
class XYZViewModel {

    var fetcher: XYZFetching!
    var service: XYZService!

    func load() -> Data {
        return fetcher.getData(service)
    }

}
依賴注入代碼
func setupMyRegistrations {
    register { XYZViewModel() }
        .resolveProperties { (resolver, model) in
            model.fetcher = resolver.optional() // Note property is an ImplicitlyUnwrappedOptional
            model.service = resolver.optional() // Ditto
        }
}


func setupMyRegistrations {
    register { XYZFetcher() as XYZFetching }
    register { XYZService() }
}
優(yōu)點(diǎn):
  • 簡(jiǎn)潔干厚。
  • 也相當(dāng)輕李滴。
缺點(diǎn):
  • 將內(nèi)部組件公開為公共變量。
  • 很難確保一個(gè)對(duì)象得到了它所需要的一切來(lái)完成它的工作蛮瞄。
  • 在注冊(cè)時(shí)還有更多的工作要做所坯。

3.構(gòu)造器注入

定義

構(gòu)造函數(shù)是Swift初始值設(shè)定項(xiàng)的Java術(shù)語(yǔ),但其思想是相同的:通過初始化函數(shù)傳遞對(duì)象所需的所有依賴項(xiàng)挂捅。

類:
class XYZViewModel {

    private var fetcher: XYZFetching
    private var service: XYZService

    init(fetcher: XYZFetching, service: XYZService) {
        self.fetcher = fetcher
        self.service = service
    }

    func load() -> Image {
        let data = fetcher.getData(token)
        return service.decompress(data)
   }

}
依賴注入代碼
func setupMyRegistrations {
    register { XYZViewModel(fetcher: resolve(), service: resolve()) }
    register { XYZFetcher() as XYZFetching }
    register { XYZService() }
}
優(yōu)點(diǎn):
  • 確保對(duì)象擁有完成其工作所需的一切包竹,因?yàn)閷?duì)象不能以其他方式構(gòu)造。
  • 將依賴項(xiàng)隱藏為私有或內(nèi)部籍凝。
  • 注冊(cè)時(shí)需要的代碼更少周瞎。
缺點(diǎn):
  • 要求對(duì)象具有具有所需所有參數(shù)的初始值設(shè)定項(xiàng)。
  • 在對(duì)象初始值設(shè)定項(xiàng)中需要更多的樣板代碼來(lái)將參數(shù)轉(zhuǎn)換為對(duì)象屬性饵蒂。

4.方法注入

定義

它不是一個(gè)模式声诸,而是直接使用解析器,羅列出來(lái)以供選擇退盯。
就像它的名字一樣彼乌,是將所需的對(duì)象注入到給定的方法中。

類:
class XYZViewModel {

    func load(fetcher: XYZFetching, service: XYZFetching) -> Data {
        return fetcher.getData(service)
    }

}
依賴注入代碼

你已經(jīng)看過了渊迁。在load函數(shù)中慰照,服務(wù)對(duì)象被傳遞到fetcher的getData方法中。

優(yōu)點(diǎn):
  • 允許調(diào)用方動(dòng)態(tài)配置方法的行為琉朽。
  • 允許調(diào)用方構(gòu)造自己的行為并將其傳遞到方法中毒租。
缺點(diǎn):
  • 將這些行為公開給使用它的所有類。
注意

在Swift中箱叁,將閉包傳遞到方法中也可以被視為方法注入的一種形式墅垮。

5.服務(wù)定位器

定義

服務(wù)定位器基本上是定位對(duì)象所需的資源和依賴項(xiàng)的服務(wù)。

從技術(shù)上講耕漱,服務(wù)定位器是它自己的設(shè)計(jì)模式算色,不同于依賴注入,但是解析器同時(shí)支持這兩種模式螟够,并且當(dāng)支持視圖控制器和初始化過程不在您控制范圍內(nèi)的其他類時(shí)灾梦,服務(wù)定位器模式特別有用。(請(qǐng)參考故事板妓笙。)

類:
class XYZViewModel {

    var fetcher: XYZFetching = Resolver.resolve()
    var service: XYZService = Resolver.resolve()

    func load() -> Data {
        return fetcher.getData(service)
    }

}
依賴注入代碼:
func setupMyRegistrations {
    register { XYZFetcher() as XYZFetching }
    register { XYZService() }
}
優(yōu)點(diǎn):
  • 更少的代碼若河。
  • 對(duì)于在初始化過程中沒有訪問權(quán)限的類,如UIViewController给郊,非常有用牡肉。
缺點(diǎn):
  • 將依賴注入系統(tǒng)公開給使用它的所有類。

6.注釋

定義

Annotation uses comments or other metadata to indication that dependency injection is required. As of Swift 5.1, we can now perform annotation using Property Wrappers. (See Annotation.)
Annotation使用注釋或其他元數(shù)據(jù)來(lái)指示需要進(jìn)行依賴項(xiàng)注入淆九。從swift5.1開始统锤,我們現(xiàn)在可以使用屬性包裝器執(zhí)行注釋毛俏。(請(qǐng)參考注釋。)

類:
class XYZViewModel {

    @Injected var fetcher: XYZFetching
    @Injected var service: XYZService

    func load() -> Data {
        return fetcher.getData(service)
    }

}
依賴注入代碼:
func setupMyRegistrations {
    register { XYZFetcher() as XYZFetching }
    register { XYZService() }
}
優(yōu)點(diǎn):
  • 更少的代碼饲窿。
  • 隱藏注冊(cè)系統(tǒng)的細(xì)節(jié)煌寇,可以很容易地創(chuàng)建一個(gè)注入的屬性包裝器來(lái)支持任何DI系統(tǒng)。
  • 對(duì)于在初始化過程中沒有訪問權(quán)限的類逾雄,如UIViewController阀溶,非常有用。
缺點(diǎn):
  • 暴露了使用依賴注入系統(tǒng)的事實(shí)鸦泳。

額外資源

這只是表面現(xiàn)象银锻。要更深入地了解利弊,請(qǐng)參閱: Inversion of Control Containers and the Dependency Injection pattern ~ Martin Fowler

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末做鹰,一起剝皮案震驚了整個(gè)濱河市击纬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钾麸,老刑警劉巖更振,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異饭尝,居然都是意外死亡肯腕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門钥平,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)实撒,“玉大人,你說我怎么就攤上這事帖池∧位螅” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵睡汹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我寂殉,道長(zhǎng)囚巴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任友扰,我火速辦了婚禮彤叉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘村怪。我一直安慰自己秽浇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布甚负。 她就那樣靜靜地躺著柬焕,像睡著了一般审残。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斑举,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天搅轿,我揣著相機(jī)與錄音,去河邊找鬼富玷。 笑死璧坟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赎懦。 我是一名探鬼主播雀鹃,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼励两!你這毒婦竟也來(lái)了褐澎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤伐蒋,失蹤者是張志新(化名)和其女友劉穎工三,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體先鱼,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俭正,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了焙畔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掸读。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宏多,靈堂內(nèi)的尸體忽然破棺而出儿惫,到底是詐尸還是另有隱情,我是刑警寧澤伸但,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布肾请,位于F島的核電站,受9級(jí)特大地震影響更胖,放射性物質(zhì)發(fā)生泄漏铛铁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一却妨、第九天 我趴在偏房一處隱蔽的房頂上張望饵逐。 院中可真熱鬧,春花似錦彪标、人聲如沸倍权。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)薄声。三九已至当船,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奸柬,已是汗流浹背生年。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留廓奕,地道東北人抱婉。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像桌粉,于是被迫代替她去往敵國(guó)和親蒸绩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容