一、概述
日期:2013-12-12
今天主要研究的是依赖注入(Dependency Injection),感觉收获很多,特别在思想上。
本人技术有限,有兴趣的朋友可以看一下文章:
①http://blog.csdn.net/wanghao72214/article/details/3969594;
②http://www.cnblogs.com/leoo2sk/archive/2009/06/17/1504693.html;
③http://baitai.iteye.com/blog/792980。
二、简介
说到依赖注入(DI),变让我想起了facade模型。这是我第一次接触到DI,于是就研究了下它。
在DI出现之前,出现了控制反转(Ioc),个人感觉它们是一样的。
以面向对象开发的软件中,实现各业务或功能,我们往往需要很多类相互配合,这样类之间的耦合度很高,
Ioc的出现就是为了解决或减少这种耦合,使得彼此之间相互独立。
实现这种技术,我们需要借助一个第三方“容器”,来“粘合”各部分组件,让他们相互运转起来。
具体详情请见上文章,下面讲下个人理解后的小例子。
三、举例
比如:现有A类(Mp3)和B类(耳机),现在想用Mp3听音乐,我们需要调用耳机中的发声方法
此时,A依赖于B的方法,A想实现听音乐的功能,就必须先示例化B的一个对象,然后通过B调用发声方法
1 //假设为耳机类,播放音乐 2 public class B 3 { 4 public void SoundRreproduction() 5 { 6 console.writeLine("我要播放音乐啦"); 7 } 8 }
public class A { B b=new B(); b.SoundReproduction(); //可以看出,A想完成该功能,必须先new 一个B对象, //注意,此时是A主动new的B,所有控制权在A上,A是主动(控制反转) }
这是一般的写法,这种写法的坏处就是,当我们改了B之后,A也要相应的修改,如换个耳机C,这A要new个C出来
下面看我们是怎样一步一步的摆脱这种耦合,使得跟换耳机后,A可以不用动。
1 //为观看方便,我把这几个类写在了一个地方,不推荐这样做 2 3 //定义一个耳机接口 4 public Interface IB 5 { 6 //依然是发声方法,偷个懒 7 void SR(); 8 } 9 10 //B类继承了IB这个耳机接口,并实现了它的SR方法 11 public class B:IB 12 { 13 public void SR() 14 { 15 console.wirteline("我要听音乐啦"); 16 } 17 } 18 19 public class A 20 { 21 IB b=new B(); 22 b.SR(); 23 //好,我们可以看到,现在的b已经不是B类了,它的本质是一个接口 24 //这是我们解耦的第一步 25 }
1 //上面虽然没有了B类,但依然需要new一个B出来这不是我们想要的 2 3 //定义一个耳机接口 4 public Interface IB 5 { 6 void SR(); 7 } 8 9 //B类继承了IB这个耳机接口,并实现了它的SR方法 10 public class B:IB 11 { 12 public void SR() 13 { 14 console.wirteline("我要听音乐啦"); 15 } 16 } 17 /*===========晕割线:上面都没变=============*/ 18 //我们在这里定义了一个耳机工厂,用来生成IB 19 public class BFactory 20 { 21 //返回一个IB接口实现类的对象 22 public static IB CreateIBImp() 23 { 24 return new B(); 25 } 26 } 27 28 public class A 29 { 30 IB b=BFactory.CreateIBImp(); 31 b.SR(); 32 } 33 34 //到了这里,我们在A中真的看不到B了,只不过当我们换耳机的时候,//要到耳机工厂中改方法这也是不符合OCP原则的
1 //上面虽然没有“成功”,但是,此时A的已经不需要new一个B了,此时它//对于B的控制权交个了工厂,当它需要B时,工厂给它创建一个B,然后//注入到A里,这便是控制反转或依赖注入 2 public Interface IB 3 { 4 void SR(); 5 } 6 public class B:IB 7 { 8 public void SR() 9 { 10 console.wirteline("我要听音乐啦"); 11 } 12 } 13 /*==========晕割线=============*/ 14 / 15 //工厂也不行,学过编程的都知道反射,我们下面用反射看看 16 17 public class A 18 { 19 MyIocContainer.Load("DI.config"); 20 IB b=MyIocContainer.Get<IB>(); 21 b.SR(); 22 } 23 24 //当我们完成者一步的时候,再次更换耳机C已经不需要改变,只需要 25 //添加(和修改是两码事)一个C继承IB接口,并实现它的方法就行了
1 public class MyIocContainer 2 { 3 private static string interface; 4 private static string implementation; 5 6 //加载配置文档 7 public static void Load (string configFile) 8 { 9 XmlDocument xmlDoc=new XmlDocument(); 10 xmlDoc.Load(configFile); 11 12 XmlNode node=doc.SelectSingleNode(@"DIObjects/IBConfig") 13 interface=node.Attributes["interface"].value; 14 implementation=node.Attributes["implementation"].value; 15 } 16 17 //反射 18 public static T Get<T>() 19 { 20 //获取接口实例的类型 21 Type impType=Type.GetType(implementation); 22 object instance=Activator.CreateInstance(impType); 23 return (T)instance; 24 } 25 }
1 1 <?xml version="1.0"?> 2 2 <DIObject> 3 3 <IBconfig name="headset" interface="IB" implementation="B" ></IBconfig> 4 4 </DIObject>