依赖倒置原则,全称Dependence Inversion Principle,英文缩写DIP。
主程序要依赖于抽象接口,不要依赖于具体实现。高层模块不应该依赖底层模块,两者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
简单地理解一下这话的意思。
依赖说的就是耦合性,如果A类依赖于B类,当B类修改或者删除了,会对A类造成很大影响,那么就可以说A类是完全为B类服务的。所以说,高层模块不应该依赖底层模块,这样耦合性太强,不利于以后的升级或拓展。
两者应该依赖于抽象。指的是它们共同有一个抽象或接口为父类,因为具体细节还没实现,所以具有拓展性。
抽象不应该依赖细节。抽象仅仅是作为定义规范,细节只需要根据规范去实现,抽象不在乎具体如何去实现。
细节应该依赖抽象。细节的实现必须严格按照指定的规范去实现接口或抽象类的方法。
下面就举个例子,一个人看书。
public class People { public void ReadStoryBook() { Console.WriteLine("read storyBook"); } }public static void Main(string[] args) { People people = new People(); people.ReadStoryBook(); }
这个People类就实现了readStoryBook的方法,但如果这个人想看其它书,那就只能继续在这个People类上添加新的方法。如果想看的书多了,那么需要添加的方法便会越来越多,同时,每次都得修改一个在运行得正常的类,容易出现问题。这就需要重新做设计。
根据依赖倒置原则的高层模块不应该依赖底层模块,这里就把人和书紧紧关联在一起,耦合性太强,高层模块方法的调用过度依赖于下层模块,不利于拓展。
那应该如何解决?两者都应该依赖于抽象,书可以抽象出来,单独定义一个Read方法。
public interface IBook { void Read(); }
把读书方法单独抽象出来,让它不依赖于People类。
public class StoryBook : IBook { public void Read() { Console.WriteLine("read storyBook"); } } public class MathBook : IBook { public void Read() { Console.WriteLine("read mathBook"); } }
将People类改一下。
public class People { public void ReadBook(IBook book) { book.Read(); } } public static void Main(string[] args) { People people = new People(); people.ReadBook(new StoryBook()); people.ReadBook(new MathBook()); }
这样,看书的方法就直接依赖于IBook接口上,拓展也变得方法,不需要去修改底层People类,每次想看不同的书,只需要new一本书就好。因为抽象不应该依赖于细节,对应IBook中的Read方法,并不关心看什么书,怎么看书,就只有看书这个动作,不关心细节。