####1.引言
对于不懂的专业术语或者专有名词,总是心存敬畏,或多或少有一种它代表多牛逼的技术的潜意识。但是当你了解之后,才发现有些术语你经常在使用,只是不知道这个术语而已,控制反转和依赖注入就是这样的术语名词,不禁让人想骂上一句MMP。(新手入行,错误的地方欢迎批评指正)
####2.示例
在使用一个简单的示例来说明这两个术语之前,需要明确两点:
- 参考了很多网友的说法,有许多人说控制反转(IoC)和依赖注入(DI)是从不同角度切入的理解形式不一样而已,这种说法我反正是理解不了,我更推崇的另一种说法,控制反转是一种设计模式或者说是一种思想,而依赖注入是这种设计模式的经典实现。也就是说二者不是一对对等概念,一个是思想,一个是实现。
- 控制反转主要解决的问题是解耦依赖对象和被依赖的对象,至于怎么解耦,下面的示例会让你大跌眼镜,因为你一直都在这么做,我确定,除非你比我还新手,否则的话你一定会感叹:“这TM不就是属性复制,参数传递吗?”
既然是控制反转,那必定就会有一个原始的“控制正转”,可能是“控制正转”存在一些缺陷所以转换思路到“控制反转”。下面的代码简单的描述了“控制正转”:
public class Programmer
{
//something else
/// <summary>
/// 控制正转
/// </summary>
public void Code_Normal()
{
IDE ide = new IDE() { MainCodeLanguage = "C#", Name = "VS2015" };
System.Console.WriteLine(ide.ToString());
}
}
public class IDE
{
public string MainCodeLanguage { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format("name:{0};langauge:{1}", this.Name, this.MainCodeLanguage);
}
}
在“控制正转”的代码中,工程师Programmer每次敲代码Code_Normal都需要重新创建一个IDE,有这个必要吗?我想换一个IDE怎么办?在这种情况下,programmer对象与其依赖的对象IDE紧密的耦合在一起,后期的变动都会带来代码的修改,违背开闭原则。
那应该怎么办?传参咯,Programmer所需要的IDE从外部注入,这是一个很正常的思路,我们把这种从外部注入的思想或者说设计模式叫做“控制反转”。既然有了思路那就剩下实现思路了,而实现“控制反转”的经典方式就是依赖注入(DI),依赖注入有三种形式:
- 构造注入,通过构造函数注入依赖对象
- Setter注入,通过属性setter方法或者类似的成员方法注入依赖对象
- 接口注入
/// <summary>
/// 构造注入
/// </summary>
public class Programmer
{
private IDE _ide;
public Programmer(IDE ide)
{
this._ide = ide;
}
public void Code_IOC()
{
if (this._ide == null)
System.Console.WriteLine("use notepad??");
System.Console.WriteLine(this._ide.ToString());
}
}
/// <summary>
/// setter注入
/// </summary>
public class Programmer
{
private IDE _ide;
public IDE CreateIDE
{
set { this._ide = value; }
}
public void Code_IOC()
{
if (this._ide == null)
System.Console.WriteLine("use notepad??");
System.Console.WriteLine(this._ide.ToString());
}
}
/// <summary>
/// 接口注入
/// </summary>
public class Programmer:ICreateIDE
{
private IDE _ide;
public void Code_IOC()
{
if (this._ide == null)
System.Console.WriteLine("use notepad??");
System.Console.WriteLine(this._ide.ToString());
}
public void CreteIDE(IDE ide)
{
this._ide = ide;
}
}
interface ICreateIDE
{
void CreteIDE(IDE ide);
}
上面的三种注入依赖对象的方式,在不同的项目环境下选择不同的方式可能会有意想不到的效果,总之一点不在内部创建IDE对象,从外部传入,那么为什么叫控制反转呢?这是区别于原来的“控制正转”,原来Programmer对象依赖IDE对象,它会每次重新创建一个IDE对象,控制权在Programmer手里,而通过依赖注入依赖对象时,控制权却不在Programmer对象手里,IDE对象是从外部传入的啊,这时候的控制权实际上是在IoC容器的手里,可以把IoC容器理解为一个装有多种IDE对象的容器,IoC容器向Programmer对象里面注入哪种IDE,Programmer对象就是用哪种,没有选择的权利,控制权是不是转换了,此所谓“控制反转”。
####3.说明
控制反转是思路的转变,我觉得是顺其自然的转变,这种转变使得对象和被依赖的对象之间灵活配置组装,从而达到解耦的目的。当然理解和灵活使用还是有很大的区别,需要在项目中根据情况来决定怎么依赖注入和积累经验。