再议依赖注入

在设计系统,进行程序开发时,常常提到这个模块依赖另外一个模块,此类依赖于另一个,那么对于依赖关系,我们一般怎么处理了?面对此问题,大家也是各有各的见解,此处

就结合个人的理解对项目中涉及到的常用依赖方式及其优缺点进行总结和探究。

在探究此问题前,想假设一种运行场景,就说一个接口提供时间服务,客户端获取时间吧。此仅仅一个场景,说明一些问题即可,那么对于此问题我们初期设计如下代码,一个提供服务的类,在客户端调用获得时间。

class SQLTimeProvider
{
public string CurrentTime
{
get
{
//SQL Select 省略
return "select getdate()";
}
}
}
class DBClient
{
public string GetTime()
{
return new SQLTimeProvider().CurrentTime;
}
}
在上边的示例通过单独定义类提供获取SQL服务器的时间服务,此时如果服务器端要求提供其它来源的时间服务,这时候我们会怎么办呢,接口呀,于是乎就在时间服务的基础上,提供了接口,
根据接口的实例化来确定调用那个服务,可参考下列代码
interface ITimerProvider
{
string CurrentTime { get; }
}
class SQLTimeProvider:ITimerProvider
{
public string CurrentTime
{
get
{
//SQL Select 省略
return "select getdate()";
}
}
}
class SQliteTimeProvider : ITimerProvider
{
public string CurrentTime
{
get
{
//SQlite Select 省略
return "select date()";
}
}
}
class DBClient
{
public string GetTime()
{
ITimerProvider Itime
= new SQLTimeProvider();
//Itime = new SQliteTimeProvider();
return Itime.CurrentTime;
}
}

这样客户端在调用时依赖于接口,服务器自由的写吧,接口一定,调用的时候统一在接口端进行处理,但这还是不爽呀,我客户端调用时必须得知道有个SQliteTimeProvider才能实例化接口,为了让过程更动态,因此还需添加一个额外提供的类,来分析要处理的数据,客户端获取数据,我就直接CurrentTime,不去管你当前是从SQLite中读取的时间,还是从SQL中读取的时间,这些对于客户端来说他也不需要知道,只需要知道当前需要显示一个合适的时间格式。额外增加一个动态解析的对象Analysis,代码如下

public class Analysis
{
Dictionary
<Type, Type> timeDictionary = new Dictionary<Type, Type>();
public Analysis()
{
timeDictionary.Add(
typeof(ITimerProvider), typeof(SQliteTimeProvider));
}
public object Create(Type curType)
{
return Activator.CreateInstance(timeDictionary[curType]);
}
public T Create<T>()
{
return (T)Create(typeof(T));
}
}

接下来客户端就要调用对应的获取时间的方法了,方法有几种呢,第一个就是客户端构造函数时,实现注入,将具体实例通过构造函数参数的方式传递给客户端,此方式具有直接行,一次性,

这种方式在一个类的最初状态就进行参数接收,不会在后继出现调用时对象为空的情况;同时此方法一经传入无法再次修改,因为实例已经创建。具体到上边的例子构造函数注入的方式代码如下:

class FormTest
{
public void ShowTime()
{
ITimerProvider timerProvider
= (new Analysis()).Create<ITimerProvider>();
//show ...
new DBClient(timerProvider).GetTime();
}
}

这样在DBClient中,通过接受一个ITimerProvider参数,把对应的业务传给它实现展现时间,此方式可能大家比较熟悉,就是把几个接口作为参数在构造函数中传递给某个对象,这就是依赖注入中的构造函数注入。

主体代码已经呈现出来了,后继的常用的依赖注入方法,还有通过属性赋值的方式,结合此例就是把一个接口直接赋值给一个对象的属性,这种方式很灵活,可以在对象的各个时候,当需要使用时进行赋值,然后读取,此方式可以结合项目实际进行运用。延伸出的还有接口注入,属性注入等;大家可以跟进实际情况,想出很多切合实际项目应用的方式。但总体就是尽量让依赖就仅仅是使用它,而不需要服务器端添加什么客户端也要做对应的修改,那样就太“依赖”了。注书中部分知识参考王翔老师的设计模式,很好的一本书。希望大家能讨论具体另外的应用方式,让项目更好开发,更易维护,更易管理。

posted @ 2011-05-29 20:59  Wendy 's  阅读(2235)  评论(12编辑  收藏  举报