控制反转 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