控制反转 IOC 与依赖注入 DI

  今天在学习过程中,有一个接触到IOC 。.netCore中已经帮助开发者实现了IOC 例如:

 
 public class HomeController : Controller
    {
        private ILogger _Logger;

        public HomeController(ILogger logger)  //依赖于抽象,具体细节的实现在IOC容器中实现
        {
            _Logger = logger;
        }
        public IActionResult Index()
        {
            _Logger.LogWarning("测试logger 警告");
            return View();
        }
}
 
//注:如果是自定义的类或者扩展的类,同时要在StartUp的 ConfigureServices方法中注册一下,才能够使用。

在学习之前先了解几个概念

DIP           依赖倒置原则
IOC          控制反转(是一种思想)
DI             依赖注入 实现IOC的一种手段
IOC容器   依赖注入的框架,用来映射依赖 ,管理对象创建和生命周期

那什么是依赖呢?通俗的讲,就是用到的地方。系统中一个类使用了另一个类是非常常见的现象。所以我们不可能完全脱离依赖。

例如在下面的案例中:

public class Person
    {
        public void Speack()
        {
            var china = new ChinaLanguage();
            china.SayHi("小小");
            china.SayBack();
        }
    }


    public class ChinaLanguage
    {
        public string SayHi(string name)
        {
            return $"你好,我是{name}";
        }

        public string SayBack()
        {
            return "我要先离开了";
        }
    }



 public class EnglishLanguage
    {
        public string SayHi(string name)
        {
            return $"hello,I'm{name}";
        }

        public string SayBack()
        {
            return "I'll back";
        }
    }

 public class Main
    {

      public void Excute()
        {
            var person = new Person();
            person.Speack();
        }
    }


 如果我要改成英文版,我就要把Speack 方法修改为如下:

 
 public void Speack()
        {
            var englishPerson = new EnglishLanguage();
            englishPerson.SayHi("小小");
            englishPerson.SayBack();
        }

 

 如果项目中海油很多地方要使用,我们这样改起来的工作量比较大,组件之间高度耦合,可扩展性较差,它违背了DIP原则。即高层模块 Person类,不应该依赖于ChinaSpeack类。下面就看一下依赖倒置原则:

依赖倒置原则:   

  • 1. 上层模块不应该依赖于下层模块,它们共同依赖于一个抽象。  
  • 2. 抽象不能依赖于具象,具象依赖于抽象。

按照上面的规则,我们应该将Person 依赖于抽象,而不是具体细节。修改如下:

 
   

    public class Person
    {
        private ILanguage _personSpeack;

        public Person(ILanguage personSpeack)
        {
            _personSpeack = personSpeack;
        }

        public void Speack()
        {
            //var china = new ChinaLanguage();
            //china.SayHi("小小");
            //china.SayBack();
            _personSpeack.SayHi("小小");
            _personSpeack.SayBack();
        }
    }

    public interface ILanguage
    {
        string SayHi(string name);

        string SayBack();
    }

    public class ChinaLanguage:ILanguage
    {
        public string SayHi(string name)
        {
            return $"你好,我是{name}";
        }

        public string SayBack()
        {
            return "我要先离开了";
        }
    }

//调用 public class Main { public void Excute() { var person = new Person(new ChinaLanguage()); //具体细节在外部实现,而不是在类内部调用 person.Speack(); } }

 这样看来,就把依赖对象的创建和绑定转移到被依赖对象类的外部来实现了。这样就实现了控制反转。(获得依赖对象的过程被反转了)

依赖注入的实现方法有三种:

构造函数注入,属性注入和接口注入。上面的案例就是构造函数注入。

讲了这么说的原理,下面稍微记录一下IOC的缺点,毕竟没有完美的框架嘛

1.首先在开发的过程中,会需要凭空多很多的接口开发。对于开发而言增加了工作量。

2.IOC 通过反射的方式运行的,在性能上会有一定的损耗。

参考文档: https://blog.csdn.net/ivan820819/article/details/79744797

https://www.cnblogs.com/liuhaorain/p/3747470.html

原文地址:https://www.cnblogs.com/kekelele/p/14601641.html