美文网首页Swift
简单欢乐的依赖注入函数

简单欢乐的依赖注入函数

作者: 快乐的小梁同学 | 来源:发表于2018-11-23 10:11 被阅读38次

    依赖注入是一种很好的解耦代码并使其更容易测试的技术。您不必让对象自己创建自己的依赖项,而是从外部注入它们,使您能够针对各种情况进行不同的设置。
    大多数时候,我们使用协议在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更复杂,还是通过协议启用依赖注入比较好,具体视情况而定,这里只是提供编程的一种思路。

    如果您有任何问题,建议或反馈,请随时与我联系~

    相关文章

      网友评论

        本文标题:简单欢乐的依赖注入函数

        本文链接:https://www.haomeiwen.com/subject/khwdqqtx.html