从面向对象编程的观点来解释ID:算法
Collaborating classes should rely on the infrastructure to provide the necessary services.数据库
依赖注入是一系列设计模式和原则,用于开发松散耦合的程序。编程
最基本的目的:可维护性。设计模式
大多数编程技术的目的是尽量高效率地提供可工做的程序。其中一个目的就是编写可维护性的代码。ide
使代码容易维护的一种方式就是松散耦合。松散耦合使代码具备可扩展性,可扩展性使代码具备可维护性。函数
四大误解单元测试
DI广泛用于延迟绑定测试
DI广泛用于单元测试spa
DI是一种抽象工厂设计
DI须要DI容器
延迟绑定
延迟绑定是一种不须要从新编译代码就能替换应用程序一部分的能力。
DI能提供延迟绑定,但二者不能划等号。
一种抽象工厂
不少人将DI当作一种服务,用于装载别的服务,也就是服务装载着(Service Locator)。但这是DI的对立面。
DI容器
DI容器是一个可选库,方便咱们组合组件,但这不是必须的。
DI的目标
替换原则,DI最重要的软件设计原则。
在软件设计中,实现同一接口的一个实现拦截另外一个实现,这个叫作装饰者模式。它能使咱们引进新的特性和方面而不用重写原有的代码。
另外一种给现有代码增长新功能的方式是对接口的当前实现用一个新的实现替代。组合模式?
还有一种就是用到了适配器模式。
使用DI的好处
延迟绑定
到运行时才肯定类型。
可扩展性
使用装饰模式来增长可扩展性。好比有一个Interface IWriteMessage,已经有一个ConsoleWriteMessage实现了这个接口,在Console中打印消息,如今须要增长一个Authentication,那么能够另外定义一个类AuthenticationWriteMessage类,它也实现IWriteMessage接口,同时它的构造函数接受一个IWriteMessage类型,在接口的方法中增长要扩展的功能,而后调用构造函数接受的类型的方法。
这个实现了开闭原则。 COMPOSITION ROOT
同时,ConsoleWriteMessage类实现最终功能,AuthenticationWriteMessage类实现验证,分离关注点。
并行开发
分离关注点后,功能能够交给不一样的开发团队并行开发。
可维护性
每一个类的职能清晰定义并受到限制,维护就变的简单多了。
这是单一职能原则。
可测试性(指单元测试)
由于遵照了依赖倒置原则,因此单元测试很容易实现。
Test Doubles
什么该注入,什么不应注入
.NET Base Library定义了不少类型,咱们引用一个程序集,而后使用其中的类型。这样是否是就是增长了耦合度?
把依赖分红稳定依赖(Stable Dependency)和可变依赖(Volatile Dependency)颇有帮助。
稳定依赖
BCL的不少模块都不会增长应用程序的耦合度。它们提供了可重用的功能来使你的代码简洁。
默认的,你能够把几乎全部定义在BCL中的类型都认为是稳定依赖。
稳定依赖的评判标准
类或模块已经存在
你预期新版本不会有破坏性的改变
算法是固定的
你不会考虑去替换这个类或模块
可变依赖
判断标准
依赖引入了这样一个需求,须要为程序建立和配置运行时环境。关系型数据库就是一个很好的例子。这种类型缺乏延迟绑定和可扩展性,使得可测试性困难。
依赖并不存在,可是它存在于开发中。一个明显的症状就是不能并行开发。
依赖不能安装在开发组织的全部机器上。好比昂贵的第三方组件。
依赖包含不肯定性的行为。
DI的边界
将建立依赖的职责从类中移出,虽然类不能对建立的过程再作控制,可是咱们开发人员能够。并且咱们能够统一建立依赖的方式。
对象组合、拦截和生命周期管理是DI的三个方面。
对象组合
为了得到可扩展性、延迟绑定和并行开发的好处,咱们使用对象组合。刚开始,DI就等同于对象组合。
对象生命周期
使用依赖注入,对象放弃了建立依赖的权利,同时也放弃了控制依赖生命周期的权利。.NET的垃圾收集器会帮咱们处理。
依赖能够为各个对象分别建立,也能够共享给各个对象。因此对象不须要控制依赖的生命周期。
若是依赖实现了IDispose接口,事情会变得比较复杂(第八章)。
拦截
当咱们把对依赖的控制交给第三方,咱们就有了在把依赖传给对象前对其进行修改的权利。也就是使用装饰模式。
经过使用拦截,咱们获得了方面编程的能力。