zoukankan      html  css  js  c++  java
  • 什么是依赖注入

    1 定义

    依赖注入(Dependency Injection),简称DI,类之间的依赖关系由容器来负责。简单来讲a依赖b,但a不创建(或销毁)b,仅使用b,b的创建(或销毁)交给容器。

    2 例子

    为了把DI讲清楚,我们需要举一个简单例子。例子足够小,希望让你能直观的了解DI而不会陷入真实示例的泥潭。

    例子:小明要杀怪,那小明拿什么武器杀怪呢?可以用刀、也可以用拳头、斧子等。

    首先,我们创建一个演员类,名字叫“小明”,具有杀怪功能。

    namespace NoInjection.ConsoleApp
    {
        public class Actor
        {
            private string name = "小明";
            public void Kill()
            {
                var knife = new Knife();
                knife.Kill(name);
            }
        }
    }
    

    然后,我们再创建一个武器-刀类,具有杀怪功能。

    using System;
    
    namespace NoInjection.ConsoleApp
    {
        public class Knife
        {
            public void Kill(string name)
            {
                Console.WriteLine($"{name}用刀杀怪");
            }
        }
    }
    

    最后,我们客户端调用演员类,执行杀怪功能。

    using System;
    
    namespace NoInjection.ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                var actor = new Actor();
                actor.Kill();
    
                Console.ReadKey();
            }
        }
    }
    

    让我们来看看输出结果:

    小明用刀杀怪
    

    通过这个例子我们可以看到,Actor类依赖Knife类,在Actor中创建Knife,执行Knife.Kill方法。我们可以回顾一下DI的定义,a依赖b,但a不创建(或销毁)b,仅使用b,显然这个不符合DI做法。

    DI下面我们详细说说DI的几种形式。

    3 形式

    3.1 构造函数注入

    首先,我们在Actor通过构造函数传入Knife。

    namespace ConstructorInjection.ConsoleApp
    {
        public class Actor
        {
            private string name = "小明";
            private Knife knife;
            public Actor(Knife knife)
            {
                this.knife = knife;
            }
    
            public void Kill()
            {
                knife.Kill(name);
            }
        }
    }
    

    然后,Knife类不需要变化。

    using System;
    
    namespace ConstructorInjection.ConsoleApp
    {
        public class Knife
        {
            public void Kill(string name)
            {
                Console.WriteLine($"{name}用刀杀怪");
            }
        }
    }
    

    最后,我们客户端来创建Actor和Knife,然后在Actor通过构造函数传入Knife。

    using System;
    
    namespace ConstructorInjection.ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                var knife = new Knife();
                var actor = new Actor(knife);
                actor.Kill();
    
                Console.ReadKey();
            }
        }
    }
    

    让我们来看看输出结果:

    小明用刀杀怪
    

    这个例子我们可以看到,Actor类依赖Knife类,但在Actor不创建Knife,而是通过构造函数传入Knife。

    3.2 Setter注入

    首先,我们在Actor类创建Knife属性。

    namespace SetterInjection.ConsoleApp
    {
        public class Actor
        {
            private string name = "小明";
            private Knife knife;
            public Knife Knife
            {
                set 
                {
                    this.knife = value;
                }
                get
                {
                    return this.knife;
                }
            }
    
            public void Kill()
            {
                knife.Kill(name);
            }
        }
    }
    

    然后,Knife类不需要变化。

    using System;
    
    namespace SetterInjection.ConsoleApp
    {
        public class Knife
        {
            public void Kill(string name)
            {
                Console.WriteLine($"{name}用刀杀怪");
            }
        }
    }
    

    最后,我们客户端来创建Actor和Knife,然后在Actor通过属性传入Knife。

    using System;
    
    namespace SetterInjection.ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                var knife = new Knife();
                var actor = new Actor();
                actor.Knife = knife;
                actor.Kill();
    
                Console.ReadKey();
            }
        }
    }
    

    让我们来看看输出结果:

    小明用刀杀怪
    

    这个例子我们可以看到,Actor类依赖Knife类,但在Actor不创建Knife,而是通过属性传入Knife。

    3.3 接口注入

    首先,我们在Actor类创建Knife属性并继承IActor

    namespace InterfaceInjection.ConsoleApp
    {
        interface IActor
        {
            Knife Knife { set; get; }
            void Kill();
        }
    }
    
    namespace InterfaceInjection.ConsoleApp
    {
        public class Actor: IActor
        {
            private string name = "小明";
            private Knife knife;
            public Knife Knife
            {
                set 
                {
                    this.knife = value;
                }
                get
                {
                    return this.knife;
                }
            }
    
            public void Kill()
            {
                knife.Kill(name);
            }
        }
    }
    

    然后,Knife类不需要变化。

    using System;
    
    namespace InterfaceInjection.ConsoleApp
    {
        public class Knife
        {
            public void Kill(string name)
            {
                Console.WriteLine($"{name}用刀杀怪");
            }
        }
    }
    

    最后,我们客户端来创建Actor和Knife,然后在Actor通过属性传入Knife。

    using System;
    
    namespace InterfaceInjection.ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                var knife = new Knife();
                IActor actor = new Actor();
                actor.Knife = knife;
                actor.Kill();
    
                Console.ReadKey();
            }
        }
    }
    

    接口注入方式我理解了也不是很透,感觉跟Setter注入没有什么大的差别,只是增加了一个接口定义。

  • 相关阅读:
    centos6.9安装xampp后报错:egrep: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
    linux如何安装xampp,以及融合dvwa
    CSS的伪元素和伪类
    Font Awesome:图标字体,完全CSS控制
    SoapUI接口测试·第一个HTTP Request接口请求和断言
    Http 四种请求访问代码 HttpGet HttpPost HttpPut HttpDelete .
    Web接口测试工具---Poster与Postman
    WebApi接口传参不再困惑(4):传参详解 一、get请求 二、post请求 三、put请求 四、delete请求 五、总结
    tomcat 禁用不安全的http请求模式 .
    JBOSS的安全配置 .
  • 原文地址:https://www.cnblogs.com/zcqiand/p/14257641.html
Copyright © 2011-2022 走看看