• 学习笔记--DI(依赖注入) 、Ioc(控制反转)


    一、概述

    日期: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 B
    public class A
    {
    B b=new B();
    b.SoundReproduction();
    //可以看出,A想完成该功能,必须先new 一个B对象,
    //注意,此时是A主动new的B,所有控制权在A上,A是主动(控制反转)
    }
    public class 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 }
    MyIocContainer
    1 1 <?xml version="1.0"?>
    2 2 <DIObject>
    3 3 <IBconfig name="headset"  interface="IB" implementation="B" ></IBconfig>
    4 4 </DIObject>
    DI.config
  • 相关阅读:
    Hibernate核心接口和类
    Struts 2基础知识
    博客开篇
    程序员的幽默笑话(深意爆笑)
    追MM的各种算法
    全局css(慕课)
    全局css
    目录的分层
    class 设置多个css属性
    Python爬虫学习:四、headers和data的获取
  • 原文地址:https://www.cnblogs.com/Ruan/p/Shinto_Ruan.html
Copyright © 2020-2023  润新知