Framework之外的IoC
IoC (Inversion of Control)是什么?软件设计大师已经作出了很多定义。这里,我从组件开发的角度来谈什么是IoC-“IoC是一种设计模式,当系统由多个组件(Component)构成时,它能消除组件间的直接依赖关系,让组件的开发更独立,使用更灵活”。
IoC是Framework的基本特征,但IoC并不专属于Framework设计范畴,它在需要消除组件依赖的地方都能发挥作用。
下面举一个开发实例:需要开发一个计算器组件,实现整数加法运算,计算过程将记录log。
针对上面的需求 ,我们开发第1版的程序:
namespace Todd
{
public class Calculator
{
public int Add(int a, int b)
{
Logger.Instance.Log(String.Format("input: {0},{1}", a, b));
int c = a + b;
Logger.Instance.Log(String.Format("result: {0}", c));
return c;
}
}
}
上面的程序编译成组件Calculator.dll,它将引用另一个组件Log.dll(可能为第三方,也可能是自己开发)。这样做的问题在于:
a. Calculator.dll对Log.dll是直接依赖关系,缺少Log.dll,Calculator的开发无法独立进行;
b. 如果其他组件User.dll需要使用Calculator的功能,它除了引用Calculator.dll外,还必须引用Log.dll。User.dll可能只需要Calculator的加法功能,不需要记录log,或者是希望把log重定向到其他地方,但Log依赖被牢牢钉在了Calculator内部,造成了User.dll使用Calculator不方便。
通过IoC,我们来解决上面的问题,下面是第2版:
{
public class Calculator
{
public delegate void Log(string message);
public Log Logger;
public int Add(int a, int b)
{
if(null != Logger) Logger.Invoke(String.Format("input: {0},{1}", a, b));
int c = a + b;
if(null != Logger) Logger.Invoke(String.Format("result: {0}", c));
return c;
}
}
从上面的代码中看到,Calculator依然拥有Log逻辑,但它不再直接依赖Log.dll了,它把对具体Log的依赖选择权交给了User.dll:
using Log;
namespace Test
{
public class User
{
public void Use()
{
Calculator cal = new Calculator();
cal.Logger = Logger.Instance.Log; //注入依赖
int r = cal.Add(1, 2);
Console.WriteLine(r);
}
}
}
通过IoC,在第2版中Calculator的开发变得独立;对Calculator的使用变得灵活。
进一步的思考:为什么Calculator内部不采用interface,而是delegate来表达Log功能?如果采用interface存在怎样的问题?有兴趣的朋友可以从实际开发使用的角度探讨!
文章开篇定义了IoC,最后再从依赖抽象和具体依赖建立的角度定义IoC:“IoC是一种设计模式,符合IoC模式的组件通过接口或委托等方式对依赖进行抽象,消除对其他组件的直接依赖,而具体的依赖关系由组件的使用者负责建立”。
本人是.Net初学者,文中错误请不吝批评指正!也欢迎对IoC有心得的朋友热情交流!
posted on 2008-09-28 13:14 Todd Wei 阅读(2766) 评论(11) 编辑 收藏 举报