0x00.前言

当我们研究一些晦涩的源码,上网查阅资料的时候,映入眼帘的总有这么些名词:DIP、IOC、DI、DL、IOC容器这些专业名词。如果不懂这些名词背后的含义,我们内心有可能是这样的:

0x01.小例子

/**
* 餐厅类
*/
public class Restaurant { //后台收银系统
private WeChatPay pay = new WeChatPay(); //收款操作
public void transact(double money) {
pay.receiveMoney(money);
}
}
import java.util.Date;

/**
* 微信
*/
public class WeChatPay {
public void receiveMoney(double money) {
System.out.println(new Date() + ",已用微信收款:" + money + "元");
}
}

这时候Restaurant类就依赖于WeChatPay,两个类产生依赖

0x02.DIP

DIP的英文名:Dependency Inversion Principle,中文名:依赖倒转原则

定义:

  • High-level modules should not depend on low-level modules. Both should depend on abstractions

  • Abstractions should not depend on details. Details should depend on abstractions

理解:

  • 高层模块不应该直接依赖于底层模块的具体实现,而应该依赖于底层的抽象。换言之,模块间的依赖是通过抽象发生,实现类之间的不发生直接依赖关系,其依赖关系是通过接口或抽象类产生的

  • 面向接口编程

它仅仅是面向对象软件设计的一种原则。它仅仅告诉你两个模块之间如何协调依赖关系,但是并没有告诉你如何做!

举个例子

我们经常所说的三层架构(UI、BLL、DAL)

图二的版本,就是高层模块依赖于低层模块的抽象,就好像依赖“倒置”。这样可以使得整体的架构更加的稳定,灵活,及自如的面对需求的变化。

0x03.IOC

  • IOC的英文名:Inversion Of Control ,中文名:控制反转
  • IOC基于DIP原则上的实现的是一种软件设计模式,它告诉你应该如何做,来解除相互依赖模块的耦合。它为相互依赖的组件提供抽象,将依赖对象的获得交给第三方来控制,即依赖对象不在被依赖的类中直接通过new来获取。
  • IOC的实现的方式一般有两种,依赖注入和依赖查找。一般DI使用的比较多

0x04.DI

  • DI的英文名:Dependency Injection,中文名称:依赖注入。
  • DI就是将依赖对象的创建和绑定转移到被依赖对象类的外部来实现。它提供是一种机制,将需要依赖(低层模块)对象的引用传递给被依赖(高层模块)对象。

DI注入有三种方式

  • 构造函数注入
  • 属性注入
  • 接口注入

Demo讲解

/**
* di Ipay 接口
*/
public interface IPay {
void receiveMoney(double money);
}
/**
* 重构后的微信支付
*/
public class WebChatPay implements IPay {
public void receiveMoney(double money) {
Date now = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(format.format(now) + ",已用重构后的微信收款:" + money + "元");
}
}
/**
* 重构后的餐厅类构造器注入
*/
public class Restaurant { private IPay _pay; public Restaurant(IPay pay) {
this._pay = pay;
} //收款操作
public void transact(double money) {
_pay.receiveMoney(money);
}
}

0x01.构造器注入

System.out.println("==========通过构造函数注入开始==============");
IPay pay = new WebChatPay();//在外部创建依赖对象
Restaurant restaurant = new Restaurant(pay);
restaurant.transact(10);
System.out.println("==========通过构造函数注入结束==============");

这时候我们就看到Restaurant将依赖的WeChatPay对象的创建和绑定转移到Restaurant类外部来实现了。这样就解除了Restaurant类与WeChatPay类的耦合关系。如果将支付方式改成Alipay,只需要定义一个Alipay类,然后在外部重新绑定依赖。不需要修改Restaurant类。

0x02.属性注入

System.out.println("==========通过属性注入开始==============");
IPay paySetter = new WebChatPay();
RestaurantBySetter restaurantSetter = new RestaurantBySetter();
restaurantSetter.setPay(paySetter);
restaurantSetter.transact(10);
System.out.println("==========通过属性注入结束==============");

0x03.接口注入

System.out.println("==========通过接口注入开始==============");
IPay payInterface = new WebChatPay();
RestaurantByInterface restaurantInterface = new RestaurantByInterface();
restaurantInterface.extraInstance(payInterface);
restaurantInterface.transact(10);
System.out.println("==========通过接口注入结束==============");

0x05.IOC容器

DI框架,用来自动创建、维护依赖对象,并管理其生命周期。

常使用的IOC容器有:

Net:Ninject、Spring.NET、Unity、Autofac等

Java:Spring等

0x06.总结

IOC带来好处:

  • 降低了各个组件之间的耦合性,增强了内聚性。
  • 大中型项目,团队分工明确,职责明确,便于测试
  • 使得模块具有热插拔特性,增加了模块的复用性

剖析DI的更多相关文章

  1. ASP.NET MVC不可或缺的部分——DI(IOC)容器及控制器重构的剖析(DI的实现原理)

    IoC框架最本质的东西:反射或者EMIT来实例化对象.然后我们可以加上缓存,或者一些策略来控制对象的生命周期,比如是否是单例对象还是每次都生成一个新的对象. DI实现其实很简单,首先设计类来实现接口, ...

  2. 从EFCore上下文的使用到深入剖析DI的生命周期最后实现自动属性注入

    故事背景 最近在把自己的一个老项目从Framework迁移到.Net Core 3.0,数据访问这块选择的是EFCore+Mysql.使用EF的话不可避免要和DbContext打交道,在Core中的常 ...

  3. Asp.Net Core下的开源任务调度平台ScheduleMaster

    从何说起 2017年初的时候,由于当时项目需要做了一个乞丐版定时调度系统,那时候只在单机上实现了核心的调度功能.做这个玩意之前也调研了社区中开源的解决方案,找了几个实地部署试跑了一下,其实都很不错.但 ...

  4. ASP.NET MVC不可或缺的部分——DI(IOC)容器及控制器重构的剖析

    ASP.NET MVC不可或缺的部分——DI(IOC)容器及控制器重构的剖析   IoC框架最本质的东西:反射或者EMIT来实例化对象.然后我们可以加上缓存,或者一些策略来控制对象的生命周期,比如是否 ...

  5. Core官方DI剖析(1)--ServiceProvider类和ServiceCollection类

    前段时间看了蒋老师的Core文章,对于DI那一块感觉挺有意思,然后就看了一下Core官方DI的源码,这也算是第一个看得懂大部分源码的框架,虽然官方DI相对来说特别简单, 官方DI相对于其它框架(例如 ...

  6. ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)

    ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件) Startup Class 1.Startup Constructor(构造函数) 2.Configure ...

  7. 深入剖析 redis AOF 持久化策略

    本篇主要讲的是 AOF 持久化,了解 AOF 的数据组织方式和运作机制.redis 主要在 aof.c 中实现 AOF 的操作. 数据结构 rio redis AOF 持久化同样借助了 struct ...

  8. 控制反转IOC与依赖注入DI【转】

    转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...

  9. WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成

    原文:WCF技术剖析之七:如何实现WCF与EnterLib PIAB.Unity之间的集成 在这之前,我写过深入介绍MS EnterLib PIAB的文章(参阅<MS Enterprise Li ...

随机推荐

  1. BZOJ3262:陌上花开(CDQ分治)

    Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),用三个整数表示. 现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量. 定义一朵花A比另一朵花B要美 ...

  2. Python语言程序设计基础(2)—— Python程序实例解析

    温度转换 def tempConvert(ValueStr): if ValueStr[-1] in ['F','f']: ans = (eval(ValueStr[0:-1]) - 32)/1.8 ...

  3. 【转】android ListView详解

    由于google doc 很多人都打不开,故更新了源码下载地址 [源码下载]----2011-01-18 在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根 ...

  4. 对枚举数据类型使用switch

  5. Maven Dependencies missing jar 解决

    在导入SVN项目之后发现Maven里面的pom.xml报错. 发现是Maven Dependencies 里面的jar包不完整. 我试过手动加入jar,但是不能成功,然后就又试着添加dependecn ...

  6. 使用带有对象的data-ng-bind

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  7. view添加毛玻璃效果两种方法

    第一种方法: UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; UIVisualEffectV ...

  8. vue里使用百度地图

    最近公司项目里要用到百度地图,然后查阅了一些资料,并总结了下: 首先呢,由于本公司使用的是百度离线地图,那么我们首先需要将百度地图离线包放置static静态文件目录下(我的离线地图包名是“baidu_ ...

  9. 关于python的GIL

    转自依云在知乎上的回答,链接为https://www.zhihu.com/question/27245271/answer/462975593 侵删. python的多线程,其实不是真的多线程,它会通 ...

  10. IDEA开发vue.js卡死问题

    在执行cnpm install后会在node_modules这个文件下面生成vue的相关依赖文件, 这个时候当执行cnpm run dev命令时,会导致IDEA出现卡死的问题,解决方法如下: