最近在学习IOC的东西,顺便写点加深自己的理解。。。
1.什么是IOC(Inversion of control-控制反转)
Ioc(inversion of control)的翻译为控制反转。这个概念其实并不新奇,在程序开发的各个环节你都有意或无意的使用到了。
控制反转顾名思义是指在程序执行时控制权的转移,比如一个控制台程序如:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void
{
Console.Write("Please Input Some Words:");
string inputData = Console.ReadLine();
Console.WriteLine(inputData);
Console.Read();
}
}
}
该控制台程序的开始执行后,OS就将控制权交给程序直到运行结束,在这个过程里所有的控制权都在程序里,这就是控制。那什么是控制反转呢?我们看一个form程序:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication10
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(textBox1.Text);
}
}
}
这个程序在运行开始时经过Application.Run 函数后将控制权交给了Windows Forms Framework框架,进入等待信息的状态,直到用户点击button1按钮,Windows Forms Framework框架或得点击信息后会调用 button1_Click()函数内的代码,此时控制权又从Windows Forms Framework框架转到了应用程序。这就是控制反转,主程序的控制权转移到了Windows Forms Framework框架。
2.IOC和依赖注入(Dependency Injection)的关系
IOC的中心思想在于控制反转,这个概念在dotnet Framework里非常常见,但是为什么这两年会引起如此多的讨论呢?Castle/srping.net/Avalon/picocontainer/objectspace等等Ioc项目又想达到什么样的目的呢?
Windows Forms Framework和Castle都反转了一部分控制权在自己身上,不同的是:Windows Forms Framework将主程序的控制权反转到自己身上;Castle将对象的配置、建立、释放等控制权转移到自己身上。两者都符合控制反转的理念,但是其初衷和目的都不相同,为了区别这两者,設計大師Martin Fowler将castle类型的IOC框架创造了一个名词:Dependency Injection(依赖注入)。
3.我们为什么需要依赖注入
依赖注入的目的是要尽量消除对象之间的依赖性,减少对象的耦合程度。但是为什么我们要消除这些依赖呢?假如我们有这样一个场景:编写一个程序需要记录运行日志,我们也许会这样写:
//主程序
class Program
{
static void
{
Console.Write("Please Input Some Words:");
string inputData = Console.ReadLine();
ILogger logger=new LoggerA();
Logger.write(inputData);
}
}
//记录类接口
Public interface ILogger
{
Public void wirtelog(string message)
}
//记录类的一个实现
Class LoggerA:ILogger
{
Public void writelog(string message)
{
……..
}
}
这个程序是基于Interface Base Programming概念来编写,这样做是为了降低program类和LoggerA的耦合关系,其实他们之间本来也没有什么耦合关系,但是由于program类使用了“ ILogger logger=new LoggerA()”来获取LoggerA的实例却使得Program类既依赖于ILogger接口也依赖于LoggerA类。我们设计的目的当然是希望Program类只依赖于ILogger接口了,但是我们如何获取实现了ILogger接口的实例(如LoggerA)呢?
在现实中这种情况还有一个名称叫:插件。我们希望Program类能够与任何事项实现了ILogger接口的类配合工作,并且允许在运行期插入具体的实现类,插入行为完全脱离Program编写者的控制,不需要重新编译Prorgram,现在的问题就集中在如何设计这个连接过程,然Program在不知道ILogger的具体实现的情况下与其协同工作。而解决这个问题的方法就可以使用IOC(控制反转),使用一个 IOC框架类来管理对象的配置、生成、释放等,程序只与IOC类进行交互来获取对象。
当然IOC框架是如何实现IOC的就需要自己慢慢研究了。
4.依赖注入的实现方式
目前依赖注入的实现方式主要有3中:构造注入、设值注入和接口注入。
种种方法都是为了降低对象之间的依赖性,但并不能消除对象之间的依赖,只是将这种依赖降到最小或者推迟依赖发生的时间(编译前依赖还是编译后依赖(插件)),甚至将其依赖性用配置文件分离出来。
为了说明几种注入方式的区别,我们假设有一个类A,还有一个类B,类B是实现IB这个接口的:
构造子注入:在类A的构造函数里出入一个参数,就是类B的实例。
设置注入:类A有一个只写属性,就是类B
接口注入:类A接受一个IB接口的参数。
这个介绍有点简单,不过确实没什么说的,具体的可以看看設計大師Martin Fowler的文章。
5.服务定位器和依赖注入
提到了依赖注入还是说说服务定位(service locator),服务定位同样可以达到和依赖注入一样的效果:消除对具体实现类的依赖,但是程序会依赖于服务定位器。服务定位器仅仅管理单独的对象创建等,而对象间的关系还是由程序处理,当然你使用代码管理还是配置文件视乎你的设计。而依赖注入则不经管理了对象的创建,还管理对象之间的依赖。
以上都是一家之言,不正确的地方请拍砖。。。。。呵呵