几张ioc的概念图
如题
暂时删除
一篇很好的ioc的文章:
我理解的IOC技术在Java和C#中比较分析
一直想用心写这个系列的文章,其实看得越多,也就越觉得自己在这方面的功力太浅,也就越不想班门弄斧啦,作为一个开篇,我想把这个技术深层次化,在之前的.net的一个MVC系列文章其实已经涉及到了,只是.net在这方面的应用不如java来得这么猛烈,这么酣汗淋漓,所以也就下定决心,这一阶段针对这一个技术点进行深层次的剖析。
IOC,英文全称Inversion of Control,中文直译控制反转,一般我们称之为“依赖注入”原则,在我还未过多涉足java领域时,在C#语言24个设计模式中(参见《大话设计模式》)有一个依赖倒转原则,作为一个设计模式的原则而不是一个模式。在接触java之后,尤其是spring框架后,被称之为“依赖注入”IOC设计模式。其实大体的意思和意义都是差不多的,只是在我看来,在C#领域对这个技术的应用没有那么广泛,限于.NET技术的先天性,我很少看到这方面的巨作,也许是我太肤浅。在我上次写基于.NET的MVC ProDinner系列文章时候,查找这方面的文章,几乎是为零,只能自己去看MVC源码或者Castle 项目源码。
首先看看《大话设计模式》中基于C#语言如何诠释这门艺术的。原著由维修计算机入题,在我们日常生活中,我们很自然地,提高计算机速度需要更高的CPU,需要更快的系统响应度就需要更好的内存,需要更大的存储介质,就需要扩大硬盘,在这一系列的活动中,于是我们就自然而然的发现,计算机速度依赖CPU,在CPU的使用中我们从来不关心CPU是怎么设计出来的,我们只需要关注这是Intel还是AMD的CPU,因为他决定了你的主板类型,当确定了CPU之后,我们只需关注你需要使用那款CPU,因为接口主板都是一样的,也即是说,大的功能不会去关注具体每一款产品的实现,而只需要关注产品与产品之间的标准化接口。由此引出来这个原则的定义:
A、高层模块不应该依赖低层模块,两个都应该依赖抽象
B、抽象不应该依赖细节,细节应该依赖抽象
这么讲其实是比较抽象的,具体到代码中实际上就是,层于层之间,各模块间,各项目间都应该使用接口层来完成模块的融合。 当某个角色(可能是一个对象实例,调用者)需要另一个角色(另一个对象实例,被调用者)的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。而控制反转中创建被调用者的工作不再由调用者来完成。创建被调用者 实例的工作通常由特定的容器来完成,然后注入调用者,因此也称为依赖注入。
废话不多说,理论讲得再精彩最终看代码实现,依据我对这些该概念的理解,我们一起看基于C#语言写出的实例:
需求场景:
父亲在完成一件事情的时候,由于各方面原因需要自己的子女帮忙才能完成,所以,父亲需要去调动自己的儿子或者女儿才能完成这件事情
类型设计:
接口 Iperson为被调用者的基类型
类 Father 调用者
类 Son 被调用者
类 Daughter 被调用者
类 Container 依赖注入容器
程序分析:
Father类通过调用抽象层接口,来完成这个操作,至于调用儿子还是女儿我们在构造函数中完成类型的选择。也就是说Father是调用者,Son和Daughter是被调用者,Container是依赖注入的生成容器。负责将调用者Son或者Daughter对象实例化给调用者。
.NET 程序目录结构:
打开visual studio 建立控制台应用程序,接口层代码实现:
1 //接口层 2 public interface Iperson 3 { 4 void operation(); 5 }
调用者代码实现:
1 //调用者实现类 2 public class Father 3 { 4 Iperson iperson; 5 6 Container container = new Container(); 7 8 public Father(String typeName) 9 { 10 iperson = container.GetApplication(typeName); 11 } 12 public void operation() 13 { 14 iperson.operation(); 15 } 16 }
Container 在这里我直接new出实例了,看到这个代码熟悉java spring框架的同学就似曾相识了,一般是用@autowired来修饰依赖注入的操作句柄。Father类中的operation方法并没有自己去实现任何操作,而是调用了iperson的操作来实现自己的方法,而iperson只是一个接口类型,需要具体的实现类,代码才能运行起来,我们看iperson的两个实现层:
//被调用者类 ipseron实现层 public class Son:Iperson { public void operation() { Console.WriteLine("son is the operator"); } } //被调用者之二 public class Daughter:Iperson { public void operation() { Console.WriteLine("daughter is the operator"); } }
Conatiner是实现容器,原理其实很简单,反射技术,反射原理进行不同的封装其实就形成了不同的技术框架,java spring的ioc核心离不开反射,许多的数据库mapper框架同样也离不开反射,看看代码实现:
//生成实例容器 public class Container { public Iperson GetApplication(String typeName) { return (Iperson) Activator.CreateInstance(Type.GetType(typeName)); } }
当然,我这是最基本的反射实现了,在生成化产品化的框架中反射远没有这么简单,但原理都是相同的。好,看下测试类实现代码:
class Program { static void Main(string[] args) { //调用son Father fa = new Father("IOCblog.Son"); fa.operation(); //调用daughter fa = new Father("IOCblog.Daughter"); fa.operation(); } }
程序运行结果:
代码写到这里对这个概念有所掌握的同学,其实会是有共鸣的,这是依赖注入最基本的实现了。
结束语:
这篇文章我们暂且不来比较依赖注入和反转的区别,依赖反转和依赖注入很多程序员把这两个概念当成一个理解,认为只是不同的解释,其实细分还是有区别的
1、依赖注入是从应用程序的角度在描述,也就是说,应用程序依赖容器创建并注入它所需要的外部资源;而控制反转是从容器的角度在描述,容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。
2、IOC,控制反转是软件运行时体现出来的一个特征:如果对象A运行时依赖于对象B,但A并不去创建B,而是从外界直接取得B。也就是说,一个对象并不是自己去创建它所依赖的其它对象。DI,依赖注入是控制反转的一种实现手段。如上面的例子,B的取得并不需要A的干涉,而是利用某些框架在通过构造参数或属性设置来实现。
关于这些这里就不展开叙述,后面我们再详细讨论,这节主要讨论依赖注入,我们首先在这节暂时认为这是一个相同的概念。
最后附上我的源代码
Java代码 http://files.cnblogs.com/aspnetdream/iocblog.rar
C#代码 http://files.cnblogs.com/aspnetdream/Csharp_IOCblog.rar
============================================================================================
暂无关于此日志的评论。