Jiacheng

aha

野比大雄

控制反转漫谈

Jiacheng / 2019-03-23


控制反转是面向对象编程的一种设计思想,常见于框架设计与使用之中,框架或容器会代替框架使用者控制对象的创建与依赖,常见的是使用依赖注入的方式实现控制反转。以上是常见的控制反转,这里谈谈控制反转这种思想上的广义延伸。

相对于一些基础类库和工具包的使用,编程者一般处于绝对的控制地位,使用那些类,调用那些函数,怎么创建对象等,都有编程者自己决定与控制。但是对与一些框架的使用,编程者便要遵守框架使用原则,需要在框架规范之内编写代码。设计优秀的框架总是解耦内聚的,并有较好扩展性,这些特性决定框架在设计之时需要从框架使用者手里分割一些控制权,这一过程已经自然而然地导致控制反转。

那么这个过程具体怎么实现呢,涵盖来讲就是通过抽象接口(包括callback,接口,抽象类,函数指针,delegate,block 等概念),在框架规范之下,框架使用者只需要面向接口编程,而程序整体流程则有框架来控制,框架通过调用接口来调用框架使用者的代码。这就类似于所谓好莱坞原则:『don’t call us, we’ll call you』。框架使用者需要做的就是正确地实现抽象接口,某些时候也需要正确地把实现注册进去。

在 Android、 iOS 开发时,控制反转更是无处不在,两者的应用开发都处于最上层的应用层,这也是应用开发者所处的一层。在这一层之下,Android 有 Framework 框架层,iOS 有 cocoa touch 框架层。开发者则在框架层的约束之下进行应用的开发。这些约束体现在什么地方呢?Application 的应用周期,Android 视图控制器 Activity、Fragment 与 iOS 视图控制器 ViewController 等的生命周期,Android 视图 View 与 iOS 视图 UIView 的生命周期以及绘制等,这些流程的逻辑控制都完全掌握在框架手中,其生命周期也不允许框架使用者调用,而应用开发者实现必要的生命周期接口,完成自己的业务需求。以一个旁观者角度来看,这就像在做一个填空题,题目如下:应用已启动,输入你要做的____,应用已显示,输入你要做的____,视图将要绘制,输入你的绘制逻辑____,应用将要进入后台,输入你要做的____。抛开应用开发者的具体实现,大体上来看,确实是在做一个大型的填空题。

不但手机应用开发,Windows 以及 Mac OS 的桌面应用开发,其框架也大体如此。对于框架使用者来说,这其实意味着完全的控制反转,但对于框架来说,这是解耦,内聚,易扩展的设计原则。

尽管使用框架从整体上来看是完全的控制反转,但框架使用者具体编码时,局部的控制「正转」与局部的控制反转同时存在,使用自己创建的类以及基础工具包编写业务逻辑时控制正转大量存在,使用回调接口进行异步任务的时候局部反转也存在。

综上,当我们选择使用一个框架的时候,或者在一个框架之下编程的时候,已经与框架之间完成了控制反转。