依赖注入与Typhoon

我一直秉持一个观点,就是有些东西你一直在用却不知道其专业的说法,等有一天你知道了自然会恍然大悟,就好比依赖注入(Dependency Injection)。

依赖注入

依赖注入是什么

依赖注入,Dependency Injection,听上去像是个贬义词,好像是被强行注入了依赖似的。其实并非如此,相反,是将依赖由外部引入,由外部确定内部需要的依赖。

举个例子,假设现在自己要开发一款天气预报 app,某个类的初始化如下:

1
2
3
4
5
6
7
8
9
10
-(id) init
{
self = [super init];
if (self)
{
// 内部硬编码了 _weatherClient 是由 GoogleWeatherClientImpl 来实现
_weatherClient = [[GoogleWeatherClientImpl alloc] initWithParameters:xyz];
}
return self;
}

嗯…好像没什么问题,但是,突然 GoogleWeather 这个 xyz 参数不好使了,那就只能改源码呗,每次不好使都要改源码…

可能你会说,搞一个单例统一返回并赋值给 _weatherClient,像这样:

1
_weatherClient = [GoogleWeatherClient sharedInstance];

嗯…好像又没什么问题,但是,突然 GoogleWeather 不好使了,被墙了,那就又只能改源码呗,每次服务提供者不好使了都要改源码,累死人…

依赖注入来了

1
2
3
4
5
6
7
8
9
-(id) initWithWeatherClient:(id<WeatherClient>)weatherClient
{
self = [super init];
if (self)
{
_weatherClient = weatherClient;
}
return self;
}

以上是在初始化的时候,注入 weatherClient,当然,也可以在对象已经初始化后对属性 _weatherClient 进行注入。

如果你还在等然后的话,对不起了,没有然后了,这就是依赖注入了。WTF,WQNMLGBD,这么高深的一个名词,就这点东西?! ╮(╯▽╰)╭我也很无奈

其实在组件化的过程中,自然而然会有对依赖注入的使用,比如,使用组件 A 时要依赖其他的组件,组件 A 并不需要在内部知道它是依赖组件 B 还是组件 C,你传给我哪个组件的依赖我就拿来用,并保持一定的鲁棒性就好了。

没有组件化?!哦…只要不是都用的全局变量来保存和传递,我觉得划分的清楚点还是可以用依赖注入的。

依赖注入有什么好处

  1. 更换某个依赖时,只需要在调用处更改即可,内部逻辑基本不用改动(上面那类例子除外,呵呵)
  2. 可测试。不用 build 一遍工程二三十分钟,然后测一下功能了,节省生命
  3. 解耦,类与类之间就划分的更加清晰了,不用一个类既要倒热水,又要擦屁股,还要换尿布了(最近几天都在搞这些  ̄▽ ̄

Typhoon

Powerful dependency injection for Cocoa and CocoaTouch. Lightweight, yet full-featured and super-easy to use.

Github 上开源的 iOS 依赖注入框架 Typhoon,可以注入方法(类方法、实例方法)、属性(普通属性、类簇属性)、注入前后调用某些方法(类似于 Aspects 中的AspectPositio)。

文章目录
  1. 1. 依赖注入
    1. 1.1. 依赖注入是什么
    2. 1.2. 依赖注入有什么好处
    3. 1.3. Typhoon