ASP.NET Core依赖注入系列教程之控制反转(IoC)(2)

现在我们将MvcLib从类库改造成一个框架,并姑且将其称为MvcFrame。如左图所示,MvcFrame的核心是一个被称为MvcEngine的执行引擎,它驱动一个编排好的工作流对HTTP请求进行一致性处理。如果我们利用MvcFrame构建一个具体的MVC应用,除了根据我们的业务需求定义相应的Controller和View之外,我们只需要初始化这个引擎并直接启动它即可。如果你曾经开发过ASP.NET MVC应用,你会发现ASP.NET MVC就是这么一个框架。

ASP.NET Core依赖注入系列教程之控制反转(IoC)

有了上面演示的这个例子作为铺垫,我们应该很容易理解IoC所谓的控制反转了。总的来说,IoC是我们设计框架所采用的设计思想,所谓的控制反转即是按照如右图所示的方式将原来实现在应用程序流程控制转移到框架中。被转移的是一个泛化的可重用的处理流程,所以IoC符合软件设计一个基本的原则,即重用性。

二、对流程的定制

ASP.NET Core依赖注入系列教程之控制反转(IoC)

我们采用IoC实现了流程控制从应用程序向框架自身的反转,但是这个被反转的仅仅是一个泛化的流程,任何一个具体的应用都可能需要对组成该流程的某些环节进行定制。如左图所示,我们将一个泛化的工作流程(A=>B=>C)被定义在框架之中,建立在该框架的两个应用需要对组成这个流程的某些环节进行定制。比如步骤A和C可以被App1重用,但是步骤B却需要被定制(B1),App2则重用步骤A和B,但是需要按照自己的方式(C2)处理步骤C。

IoC将对流程的控制从应用程序转移到框架之中,框架利用一个引擎驱动整个流程的执行。换句话说,应用程序无需关心该工作流程的细节,它只需要启动这个引擎即可。但是这个引擎一旦被启动,框架就会完全按照预先编排好的流程进行工作,如果应用程序希望整个流程按照自己希望的方式被执行,针对流程的定制一般在发生在启动引擎之前。

一般来说,框架会以相应的形式提供一系列的扩展点,应用程序则通过定义扩展的方式实现对流程某个环节的定制。在引擎被启动之前,应用程序将所需的扩展注册到框架之中。一旦引擎被正常启动,这些注册的扩展会自动参与到整个流程的执行过程中。

虽然应用程序是框架引擎的启动着,但是一旦引擎被启动之后它就丧失了对流程的控制,应用程序对流程的定制不是在执行过程中对框架的干预来完成的,而只需要在流程执行之前就将定制的部分准备好,框架自身在执行过程中会智能地选择它们。从这个意义上讲,IoC对流程的定制遵循着这样一个原则,即“Don't call us, we'll call you!”,它被称为好莱坞原则。

综上所述,IoC一方面通过流程控制从应用程序向框架的反转实现了针对流程自身的重用,另一方面采用“好莱坞原则”使得这个被重用的流程可能自由地被定制,这两个因素实际上决定了框架自身的价值。重用让框架不仅仅是为应用程序提供实现单一功能的API,而是提供一整套可执行的解决方案;可定制则使我们可以为不同的应用程序对框架进行定制,这无疑让框架可以使用到更多的应用之中。

三、 IoC模式

正如我们在上面提到过的,很多人将IoC理解为一种“面向对象的设计模式”,实际上IoC自身不仅与面向对象没有必然的联系,它也算不上是一种设计模式。一般来讲,设计模式提供了一种解决某种具体问题的方案,但是IoC既没有一个针对性的问题领域,其自身没有提供一种可实施的解决方案,所以我更加倾向于将IoC视为一种设计原则,实际上很多我们熟悉的设计模式背后采用了IoC原则。

模板方法(Template Method)

提到IoC,很多人首先想到的是DI,但是在我看来与IoC联系得最为紧密的则是另一种被称为“模板方法”的设计模式。模板方法模式与IoC的意图可以说完全一致,该模式主张将一个可复用的工作流程或者由多个步骤组成的算法定义成模板方法,组成这个流程或者算法的步骤则实现在相应的虚方法之中,模板方法根据流程先后调用这些虚方法。所有这些方法均定义在同一个类中,我们可以通过派生该类并重写相应的虚方法达到对流程定制的目的。

对于上面我们演示的这个MVC的例子,我们可以将整个请求处理流程实现在如下一个MvcEngine类中,请求的监听与接收、目标Controller的激活与执行以及View的呈现则分别定义在四个受保护的虚方法中,模板方法Start根据预定义的请求处理流程先后调用这四个方法。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdsjsx.html