Skip to content

设计模式之——依赖反转

✨文章摘要(AI生成)

本文介绍了面向对象设计中的依赖反转原则(Dependency Inversion)。文章首先解释了依赖反转的核心概念:高层模块应该依赖于抽象接口而非具体实现。随后通过 TypeScript 中的实际例子,展示了如何使用接口和依赖注入来实现依赖反转,以 useStorage 方法为例说明了如何通过抽象接口实现代码的解耦和扩展。最后总结了依赖反转带来的好处,包括代码解耦、可扩展性和可测试性的提升。

依赖反转(Dependency Inversion)是面向对象设计中的一种设计原则,它强调高层模块不应该依赖于低层模块的具体实现,而是应该依赖于抽象接口或协议。这个原则是由罗伯特·C·马丁(Robert C. Martin)提出的,也是SOLID原则中的其中一个。

原理

  • 高层模块应该依赖于抽象接口或协议,而不是具体实现。
  • 抽象接口或协议应该由低层模块来实现。

具体来说,依赖反转可以通过以下方式实现:

  1. 定义抽象接口或协议,描述高层模块所需的功能。
  2. 高层模块通过依赖注入(Dependency Injection)或者工厂模式等方式,将具体实现的依赖关系传递给低层模块。
  3. 低层模块实现抽象接口或协议,并提供具体的功能实现。
  4. 高层模块通过抽象接口或协议来使用低层模块的功能,而不需要关心具体实现。

例子

将函数的内部易变的逻辑抽象为参数,带来更好的可维护性,这里先以vue use 中的 useStroage 方法为例

ts
// 定义通用接口
export interface StorageLike {
  getItem(key: string): string | null
  setItem(key: string, value: string): void
  removeItem(key: string): void
}

//  定义函数签名
// 函数签名中storage参数为外部传入,可以是SessionStorage也可以是LocalStroage可以是自定义的对StorageLike接口的实现
function useStorage(key: string, storage?: StorageLike): RemovableRef<string>

// 使用示例
const id = useStorage('my-id', sessionStorage) ;
const id = useStorage('my-id', localStorage) 

// 自定义stroage,比如对indexdb的封装,只要实现了StorageLike接口就可以复用useStorage中通用的逻辑
class CustomStorage implements StorageLike {
    getItem(key) {...}
    setItem(key, value){....}
    removeItem(key: string) {...}
}

const customStorage = new CustomStorage()
const id = useStorage('my-id', customStorage)

总结

  1. 解耦:高层模块和低层模块之间的依赖关系被解耦,使得代码更加灵活和可维护。
  2. 可扩展性:通过替换具体实现,可以轻松地扩展系统的功能。
  3. 可测试性:依赖反转使得高层模块的测试更加容易,可以使用模拟对象或者桩对象来替代具体实现。

Last updated: