.NET里简易实现IoC
前言
在前面的篇幅中对依赖倒置原则和IoC框架的使用只是做了个简单的介绍,并没有很详细的去演示,可能有的朋友还是区分不了依赖倒置、依赖注入、控制反转这几个名词,或许知道的也只是知道依赖倒置是原则,依赖注入、控制反转都是实现的方式,我将在下面对这些个名词做详细的介绍,在篇幅的最后还会自己实现了IoC容器的功能。
依赖倒置原则
我们先来看一段代码,代码1-1
public class Top { public void Execution() { Underly underly = new Underly(); underly.WriterLine(); } } public class Underly { public void WriterLine() { Console.WriteLine("这是底层类型的输出"); } }
从代码1-1中看到Top类型的Execution()方法中包含了对Underly的依赖,直接使用的New来实例化Underly类型,致使两个类型之间的耦合是属于强耦合类型,这样做会导致在需求发生变化的时候对于底层类型也就是Underly的修改会牵动到Top中的现实,而我们是不希望这种事情发生。
这个时候我们再看依赖原则的定义(度娘的):
A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
B.抽象不应该依赖于具体,具体应该依赖于抽象。
A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象
对于A,照着字面意思来说的话很简单了,已经没法办再用文字来描述了,看代码吧,
代码1-2
public class Top { public void Execution() { IUnderly underly = new Underly(); underly.WriterLine(); } } public interface IUnderly { void WriterLine(); } public class Underly:IUnderly { public void WriterLine() { Console.WriteLine("这是底层类型的输出"); } }
在代码1-2中我们对Underly进行了抽象,并且让其依赖于抽象(也就是实现接口),而在Top类型中也依赖于抽象了。
图1
图1中所示的就是代码1-2所要表示的类型结构了,也就是依赖倒置原则中A的实现,从图1中我们可以看到依赖倒置原则里还装着开放封闭原则,这里所要说明的意思就是依赖倒置原则是开放封闭原则的基础。
从图1中的结构来看,如果是站在开放封闭原则的角度来看也是没有问题的,对扩展开放对修改关闭,在需求变动的时候只要重新实现个依赖于抽象的下层,利用多态则可实现对扩展开放。
如果是站在依赖倒置原则的角度去看,那就是符合了依赖倒置原则定义的A条。
(Ps:这里有的朋友可能会说上面的示例中Top也依赖于具体了,我只想说请注意你的人身安全,我这个人脾气不太好。
开个玩笑,对于Top也依赖于具体的事确实是有的,后面会有说明)
B.抽象不应该依赖于具体,具体应该依赖于抽象
对于依赖倒置原则定义的B来说,我分两个部分来给大家解释一下。
第一个部分就是抽象不应该依赖于具体, 我们还是通过代码来说明吧。
代码1-3
public interface IUnderly { void WriterLine(); IWriter CreateWriterInstance(); } public class Underly:IUnderly { public void WriterLine() { CreateWriterInstance().WriterLine(); } public IWriter CreateWriterInstance() { return new Writer(); } } public interface IWriter { void WriterLine(); } public class Writer : IWriter { public void WriterLine() { Console.WriteLine("这只是一个输出"); } }
首先我们新定义了一种输出方式Writer和它的抽象IWriter接口类型,我们想把它应用到Underly类型的输出中,然后我们修改了Underly的抽象类型也就是在IUnderly接口类型中新添加了一个CreateWriterInstance()方法,并且这个方法的返回类型是Writer的抽象,这样就对应了依赖倒置原则定义中B条的前半句话:抽象不应该依赖于具体。
错误的示范,代码1-4
public interface IUnderly { void WriterLine(); Writer CreateWriterInstance(); }
这里这样的坏处很多后果也很严重,就不去细说了慢慢体会一下应该会感觉得到。
从依赖倒置原则定义中B条的前半句话中来看,我们可以在硕大的.NET Framework中看一下一些抽象的定义中是否有依赖于具体的,应该是没有至少我是没发现。
对于B条定义的后半句话,也就是第二个部分:具体应该依赖于抽象,这部分的内容就是约束我们在实际运用设计原则的时候会出现的问题,就好比上面的Top类型依然是依赖于具体了。
对于怎么解决这样的一个问题,有的朋友可能已经想到了,对的那就是依赖注入,都说依赖注入是依赖倒置原则的实现方式,这是不完全的,依赖注入解决的问题是将具体到具体的依赖转换成具体到抽象的依赖。我是这么认为的,纯属个人观点。
(ps:这是一种治标不治本的方法,DI把对象耦合的问题抛到了外部,也就是这样才导致了IoC的诞生,后面会有介绍。)
依赖注入
图2
对于上节中的示例中对象所依赖的图示。为了能像图1中所示的结构那样以及符合依赖倒置原则的定义,我们将使用依赖注入的方式,先暂时性的解决这样的问题。
依赖注入有三种方式,意思都差不多都是讲外部抽象的引用设置到内部来从而实现注入。
这里就简单示例一下,