依賴注入是一種很好的解耦程式碼並使其更容易測試的技術。您不必讓物件自己建立自己的依賴項,而是從外部注入它們,使您能夠針對各種情況進行不同的設定。 大多數時候,我們使用協議在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更復雜,還是通過協議啟用依賴注入比較好,具體視情況而定,這裡只是提供程式設計的一種思路。
如果您有任何問題,建議或反饋,請隨時與我聯絡~