《转载的这个up的其他的文章也很nice》
面向对象设计(OOD)有助于我们开发出高性能、易扩展以及易复用的程序。
其中,OOD有一个重要的思想那就是依赖倒置原则(DIP)(啥特么意思,倒置?瓶子倒置的意思吗),并由此引申出IoC、DI以及Ioc容器等概念。
通过本文我们将一起学习这些概念,并理清他们之间微妙的关系。
依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念)。
控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式)。
依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式)。
IoC容器:依赖注入的框架,用来映射依赖,管理对象创建和生存周期(DI框架)
依赖倒置原则(DIP)(我特么读着都瘪嘴)
相信大部分取过钱的朋友都深有感触,只要有一张卡,随便到哪一家银行的ATM都能取钱。
在这个场景中,ATM相当于高层模块,而银行卡相当于低层模块。ATM定义了一个插口(接口),供所有的银行卡插入使用。
也就是说,ATM不依赖于具体的哪种银行卡。它只需定义好银行卡的规格参数(接口),所有实现了这种规格参数的银行卡都能在ATM上使用。现实生活如此,软件开发更是如此。
依赖倒置原则,它转换了依赖,高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口。
通俗的讲,就是高层模块定义接口,低层模块负责实现。
其实再通俗的说就是:想到依赖倒置:就想到高层与底层(高层是接口,底层是实现接口;接口才不管谁实现了它,底层只要满足高层的参数需要就能实现高层的方法。)
感觉总而言之:依赖倒置就是高层是接口,底层是继承接口的各种方法;好处也就是接口的好处.
控制反转(IoC)
IoC则是一种 软件设计模式,它告诉你应该如何做,来解除相互依赖模块的耦合。
控制反转(IoC),它为相互依赖的组件提供抽象(握草,提供抽象,抽象???),
将依赖(低层模块)对象的获得交给第三方(系统)来控制,即依赖对象不在被依赖模块的类中直接通过new来获取。//是不是就是说,"底层"的类,不直接继承接口,而是底层-->第三方-->高层接口
在图1的例子我们可以看到,ATM它自身并没有插入具体的银行卡(工行卡、农行卡等等),而是将插卡工作交给人来控制(人就是第三方啦),即我们来决定将插入什么样的银行卡来取钱。
同样我们也通过软件开发过程中场景来加深理解。
做过电商网站的朋友都会面临这样一个问题:订单入库。假设系统设计初期,用的是SQL Server数据库。通常我们会定义一个SqlServerDal类,用于数据库的读写。
public class SqlServerDal { public void Add() { Console.WriteLine("在数据库中添加一条订单!"); } }
然后我们定义一个Order类,负责订单的逻辑处理。由于订单要入库,需要依赖于数据库的操作。因此在Order类中,我们需要定义SqlServerDal类的变量并初始化。
public class Order { private readonly SqlServerDal dal = new SqlServerDal();//添加一个私有变量保存数据库操作的对象 public void Add() { dal.Add(); } }
写个控制台来实现一下
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DIPTest { class Program { static void Main(string[] args) { Order order = new Order(); order.Add(); Console.Read(); } } }
OK,结果看起来挺不错的!正当你沾沾自喜的时候,这时BOSS过来了。“小刘啊,刚客户那边打电话过来说数据库要改成Access”,“对你来说,应当小CASE啦!”BOSS又补充道。带着自豪而又纠结的情绪,我们思考着修改代码的思路。
由于换成了Access数据库,SqlServerDal类肯定用不了了。因此,我们需要新定义一个AccessDal类,负责Access数据库的操作。
public class AccessDal { public void Add() { Console.WriteLine("在ACCESS数据库中添加一条记录!"); } }
然后,再看Order类中的代码。由于,Order类中直接引用了SqlServerDal类的对象。所以还需要修改引用,换成AccessDal对象。
显然,这不是一个良好的设计,组件之间高度耦合,可扩展性较差,它违背了DIP原则。
高层模块Order类不应该依赖于低层模块SqlServerDal,AccessDal,两者应该依赖于抽象。
那么我们是否可以通过IoC来优化代码呢?答案是肯定的。IoC有2种常见的实现方式:依赖注入和服务定位。
其中,依赖注入使用最为广泛。下面我们将深入理解依赖注入(DI),并学会使用。
依赖注入(DI)
先copy到这吧。。。