Swift依赖注入:直接注入与注入符合协议依赖的区别是什么
构造器依赖注入两种实现方式的差异
以下是两种实现的示例代码:
直接注入具体依赖类型示例
struct Engine { func start() { print("Start") } func stop() { print("Stop") } } struct Car { let engine: Engine init(engine: Engine) { self.engine = engine } }
注入符合协议的依赖类型示例
protocol EngineProtocol { func start() func stop() } struct Engine: EngineProtocol { func start() { print("Start") } func stop() { print("Stop") } } struct Car { let engine: EngineProtocol init(engine: EngineProtocol) { self.engine = engine } }
核心差异对比
- 耦合度不同
直接注入具体类型时,Car和Engine强绑定,依赖的具体类型不可替换,只要后续需要更换发动机实现,就必须修改Car本身的代码;注入协议类型时,Car只和抽象的协议绑定,和具体的实现类完全解耦。 - 扩展性不同
直接注入具体类型的方案完全不支持无侵入扩展,新增任何发动机类型都需要改动Car的代码;注入协议的方案完全符合开闭原则,后续新增燃油发动机、电动发动机等实现,只需要让新类型遵守EngineProtocol即可,不需要修改Car的任何逻辑。 - 可测试性不同
直接注入具体类型时,单元测试Car的逻辑无法隔离Engine的影响,如果Engine的实现包含复杂的IO、硬件调用逻辑,会大幅提升测试成本;注入协议类型时,可以直接构造MockEngine遵守协议,模拟各种返回值或者调用状态,完全隔离依赖实现,测试效率和准确性更高。 - 性能表现不同
直接注入具体值类型时,编译器可以做完整的静态优化,没有额外的运行时开销;注入协议类型时,存在少量的动态派发开销,不过绝大多数业务场景下这个开销可以忽略不计,Swift 5.7+ 也可以通过some/any关键字进一步优化这部分的性能损失。
内容的提问来源于stack exchange,提问作者Karen Nikoghosyan
相关产品推荐
相关产品推荐

