簡單歡樂的依賴注入函式

快樂的小樑同學發表於2018-11-26

依賴注入是一種很好的解耦程式碼並使其更容易測試的技術。您不必讓物件自己建立自己的依賴項,而是從外部注入它們,使您能夠針對各種情況進行不同的設定。 大多數時候,我們使用協議在Swift中啟用依賴注入。雖然當我們的API更復雜時基於協議的依賴注入很好,但當它只有一個目的(並且只需要一個方法)時,我們可以通過簡單地使用函式來降低我們的複雜性。 例如我們編寫一個簡單的英雄選擇邏輯,我用使用randomizer從英雄池中隨機的抽取英雄如下所示,最開始我們可能會這樣寫:

struct Hero {
    var name: String = "name"
    //...
}

class LOLGame {
    private let heros: [Hero]

    init(heros: [Hero]) {
        self.heros = heros
    }

    func randomHero() -> Hero {
        let index = Int(arc4random_uniform(UInt32(heros.count)))
        return heros[index]
    }
}

class AViewController: UIViewController {
    func chooseHero() -> Hero  {
        let manager = LOLGame(heros: [Hero(name: "劍聖"), Hero(name: "皇子"), Hero(name: "德瑪")])
        return manager.randomHero()
    }
}

複製程式碼

如果我每次玩遊戲時要更換選英雄的規則,怎麼辦呢?我們通常會再給LOLGame加上類似hero(at index:index) -> Hero 方法。但是如果我們能從外部注入依賴,情況看上去就會好得多,經過調整,程式碼如下

struct Hero {
    var name: String = "name"
    //...
}

class LOLGame {
    typealias Randomizer = (UInt32) -> UInt32

    private let heros: [Hero]
    private let randomizer: Randomizer
    
    init(heros: [Hero], randomizer: @escaping Randomizer = arc4random_uniform ) {
        self.heros = heros
        self.randomizer = randomizer
    }
    
    func selectedHero() -> Hero {
        let index = Int(randomizer(UInt32(heros.count)))
        return heros[index]
    }
}

class AViewController: UIViewController {
    func chooseHero() -> Hero  {
        let manager = LOLGame(heros: [Hero(name: "劍聖"), Hero(name: "皇子"), Hero(name: "德瑪")])
        return manager.selectedHero()
    }
    
    func allowChooseJS() -> Hero {
        let manager = LOLGame(heros:  [Hero(name: "劍聖"), Hero(name: "皇子"), Hero(name: "德瑪")]) {_ in 
            return 0
        }
        return manager.selectedHero()
    }
    
    func chooseHero(at index: UInt32) -> Hero {
        let manager = LOLGame(heros:  [Hero(name: "劍聖"), Hero(name: "皇子"), Hero(name: "德瑪")]) {_ in
            return index
        }
        return manager.selectedHero()
    }
}
複製程式碼

這樣改動後,可以在不動LOLGame的情況下,擴充套件功能。 這種定義API的好處在於"設計支援變化",如果API更復雜,還是通過協議啟用依賴注入比較好,具體視情況而定,這裡只是提供程式設計的一種思路。

如果您有任何問題,建議或反饋,請隨時與我聯絡~

相關文章