如何将单例模式与依赖注入结合使用?

iOShit我搞砸了

我最近听说,使用依赖注入是“在当今软件开发领域中使用单例的唯一社会上可接受的方式”。我不必立即就此声明的准确性进行辩论,因为它主要是基于观点的。我现在的目标是了解如何将依赖注入与单例模式一起使用。

例如,在最新的iOS应用中,我有一个Service层,用于保存URLSession代码。我将此层创建为单例:

struct ServiceSingleton {

    private init()

    static let shared = ServiceSingleton()

    func fetchJSON() {
     // URLSession code
    }

}

然后shared,我在ViewController中使用,如下所示:

class ViewController: UIViewController() {

    override viewDidLoad() {
        super.viewDidLoad()

        fetchData()    

    }

    fileprivate func fetchData() {

        ServiceSingleton.shared.fetchJSON()
    }

}

当然,上面的代码使用单例,但不使用依赖项注入。我知道,如果我想一般使用依赖注入,我会在ViewController中添加如下内容

// Dependency Injection Constructor
override init(someProperty: SomePropertyType) {
    self.someProperty = someProperty
    super.init()
}

TL; DR:

(1)您能告诉我如何在Swift中的单例模式中正确使用依赖注入吗?

(2)您能告诉我这能达到什么目的吗?

(3)从现在开始在我的iOS项目中使用单例模式时,是否应该始终使用DI?

亚力山大
  1. 您能告诉我如何在Swift中的单例模式中正确使用依赖注入吗?

    而不是ServiceSingleton.shared直接访问,您将访问实例变量,该实例变量通常在初始化程序中(如果可能的话)注入到您的对象中,否则作为可设置的属性(初始化后):

    protocol FooService {
        func doFooStuff()
    }
    
    class ProductionFooService: FooService {
    
        private init() {}
    
        static let shared = ProductionFooService()
    
        func doFooStuff() {
            print("real URLSession code goes here")
        }
    
    }
    
    struct MockFooService: FooService {
        func doFooStuff() {
            print("Doing fake foo stuff!")
        }
    }
    
    class FooUser {
        let fooService: FooService
    
        init(fooService: FooService) { // "initializer based" injection
            self.fooService = fooService
        }
    
        func useFoo() {
            fooService.doFooStuff() // Doesn't directly call ProductionFooService.shared.doFooStuff
        }
    }
    
    let isRunningInAUnitTest = false
    
    let fooUser: FooUser
    if !isRunningInAUnitTest {
        fooUser = FooUser(fooService: ProductionFooService.shared) // In a release build, this is used.
    }
    else {
        fooUser = FooUser(fooService: MockFooService()) // In a unit test, this is used. 
    }
    
    fooUser.useFoo()
    

    通常,ViewController的初始化是由情节提要板完成的,因此您无法通过初始化参数来依赖于依赖关系,而必须使用在对象初始化之后设置的存储属性。

  2. 您能告诉我这能达到什么目的吗?

    您的代码不再与耦合ProductionFooService.shared因此,您可以引入的不同实现FooService,例如用于beta环境的实现,用于单元测试的模拟实现等。

    如果您的所有代码普遍直接使用您的产品依赖关系,您将...

    1. 发现不可能在测试环境中实例化对象。您不希望将单元测试,CI测试环境,beta环境等连接到产品数据库,服务和API。

    2. 没有真正的“单元”测试。每个测试都将测试一个代码单元,以及其传递依赖的所有常见依赖关系。如果您要对这些依赖关系之一进行代码更改,那么它将破坏系统中的大多数单元测试,这将使得更难以准确确定失败的原因。通过分离依赖关系,您可以使用模拟对象,这些对象至少要做支持单元测试所需的最低限度的工作,并确保每个测试仅测试特定的代码单元,而不测试其依赖的可传递依赖关系。

  3. 从现在开始,当我在iOS项目中使用单例模式时,是否应该始终使用DI?

    这是个好习惯。当然,有些quicik和dirty项目只是想快速移动而不会真正关心,但是会让您感到惊讶的是,这些所谓的quicik和dirty项目实际上起飞了多少,并且付清一切费用。您只需要意识到自己何时会受到阻碍,就不必花一些额外的时间来分离体面。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Julia如何将值识别为单例类型?

来自分类Dev

如何将更复杂的控制器名称注册为单例/非单例?

来自分类Dev

将单例与依赖项注入结合使用(城堡温莎堡)

来自分类Dev

正确使用单例模式

来自分类Dev

在python中,如何使用单例模式?

来自分类Dev

Swift-如何将单例设置为nil

来自分类Dev

如何使用简单的注入器将类型与其接口注册为单例?

来自分类Dev

ASP.NET Web Api依赖注入-是否单例

来自分类Dev

如何注入具有单例作用域依赖性的Grails 2.4.x服务?

来自分类Dev

在使用gson转换器时,如何将改造用作单例?

来自分类Dev

Angular 2依赖注入单例

来自分类Dev

单例vs依赖注入

来自分类Dev

Blazor全局单例对象-使用依赖注入?

来自分类Dev

单例或依赖注入

来自分类Dev

Julia如何将值识别为单例类型?

来自分类Dev

如何将更复杂的控制器名称注册为单例/非单例?

来自分类Dev

如何在Android中使用Roboguice将Google番石榴事件总线作为全局单例注入?

来自分类Dev

将单例与依赖项注入配合使用(城堡温莎堡)

来自分类Dev

依赖注入与单例,初始化

来自分类Dev

使用单例模式

来自分类Dev

在MVP设计中,两个演示者如何在不使用单例模式或依赖项注入的情况下互相交谈?

来自分类Dev

无法理解如何使用单例模式?

来自分类Dev

在python中,如何使用单例模式?

来自分类Dev

依赖注入中的单例

来自分类Dev

如何注入具有单例作用域依赖性的Grails 2.4.x服务?

来自分类Dev

如何转向单例类的依赖注入

来自分类Dev

如何将命令模式与 JavaFX GUI 结合使用?

来自分类Dev

如何将一个 blueprint.xml 中的单例 bean 注入到单独的 blueprint.xml 中?

来自分类Dev

依赖注入单例到瞬态

Related 相关文章

  1. 1

    Julia如何将值识别为单例类型?

  2. 2

    如何将更复杂的控制器名称注册为单例/非单例?

  3. 3

    将单例与依赖项注入结合使用(城堡温莎堡)

  4. 4

    正确使用单例模式

  5. 5

    在python中,如何使用单例模式?

  6. 6

    Swift-如何将单例设置为nil

  7. 7

    如何使用简单的注入器将类型与其接口注册为单例?

  8. 8

    ASP.NET Web Api依赖注入-是否单例

  9. 9

    如何注入具有单例作用域依赖性的Grails 2.4.x服务?

  10. 10

    在使用gson转换器时,如何将改造用作单例?

  11. 11

    Angular 2依赖注入单例

  12. 12

    单例vs依赖注入

  13. 13

    Blazor全局单例对象-使用依赖注入?

  14. 14

    单例或依赖注入

  15. 15

    Julia如何将值识别为单例类型?

  16. 16

    如何将更复杂的控制器名称注册为单例/非单例?

  17. 17

    如何在Android中使用Roboguice将Google番石榴事件总线作为全局单例注入?

  18. 18

    将单例与依赖项注入配合使用(城堡温莎堡)

  19. 19

    依赖注入与单例,初始化

  20. 20

    使用单例模式

  21. 21

    在MVP设计中,两个演示者如何在不使用单例模式或依赖项注入的情况下互相交谈?

  22. 22

    无法理解如何使用单例模式?

  23. 23

    在python中,如何使用单例模式?

  24. 24

    依赖注入中的单例

  25. 25

    如何注入具有单例作用域依赖性的Grails 2.4.x服务?

  26. 26

    如何转向单例类的依赖注入

  27. 27

    如何将命令模式与 JavaFX GUI 结合使用?

  28. 28

    如何将一个 blueprint.xml 中的单例 bean 注入到单独的 blueprint.xml 中?

  29. 29

    依赖注入单例到瞬态

热门标签

归档