依赖注入类型

此示例将演示如何使用以下方法在 Swift 中使用依赖注入( DI )设计模式:

  1. 初始化注入 (正确的术语是构造函数注入,但由于 Swift 具有初始化程序,因此称为初始化程序注入)
  2. 属性注入
  3. 方法注入

没有 DI 的示例设置

    protocol Engine {
        func startEngine()
        func stopEngine()
    }
    
    class TrainEngine: Engine {
        func startEngine() {
            print("Engine started")
        }
        
        func stopEngine() {
            print("Engine stopped")
        }
    }
    
    protocol TrainCar {
    var numberOfSeats: Int { get }
    func attachCar(attach: Bool)
}

class RestaurantCar: TrainCar {
    var numberOfSeats: Int {
        get {
            return 30
        }
    }
    func attachCar(attach: Bool) {
        print("Attach car")
    }
}

class PassengerCar: TrainCar {
    var numberOfSeats: Int {
        get {
            return 50
        }
    }
    func attachCar(attach: Bool) {
        print("Attach car")
    }
}
    
class Train {
    let engine: Engine?
    var mainCar: TrainCar?
}

初始化依赖注入

顾名思义,所有依赖项都是通过类初始化程序注入的。要通过初始化程序注入依赖项,我们将初始化程序添加到 Train 类。

火车课现在看起来像这样:

class Train {
    let engine: Engine?
    var mainCar: TrainCar?
    
    init(engine: Engine) {
        self.engine = engine
    }
}

当我们想要创建 Train 类的实例时,我们将使用初始化器来注入特定的 Engine 实现:

let train = Train(engine: TrainEngine())

注意: 初始化器注入与属性注入的主要优点是我们可以将变量设置为私有变量,或者甚至使用 let 关键字使其成为常量(正如我们在示例中所做的那样)。这样我们就可以确保没有人可以访问它或更改它。

属性依赖注入

DI 使用属性甚至比使用初始化程序更简单。让我们使用属性 DI 将已经创建的列车对象注入 PassengerCar 依赖关系:

train.mainCar = PassengerCar()

而已。我们的火车的 mainCar 现在是一个 PassengerCar 实例。

方法依赖注入

这种类型的依赖注入与前两种有点不同,因为它不会影响整个对象,但它只会注入一个依赖项,以便在一个特定方法的范围内使用。当依赖关系仅在单个方法中使用时,通常不能使整个对象依赖于它。让我们为 Train 类添加一个新方法:

func reparkCar(trainCar: TrainCar) {
    trainCar.attachCar(attach: true)
    engine?.startEngine()
    engine?.stopEngine()
    trainCar.attachCar(attach: false)
}

现在,如果我们调用新的 Train 类方法,我们将使用方法依赖注入注入 TrainCar

train.reparkCar(trainCar: RestaurantCar())