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. 【[SCOI2007]修车】

    题目 只能做网络流度日了 当然是要对每个修车的人拆点,把每个人拆成\(n\)个点用于接收不同时刻的车 每个车\(i\)向每个时刻\(k\)的人\(j\)连边,边权为\(t[i][j]*k\)这样就是这 ...

  2. 【转】Android listview与adapter用法

    一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常 ...

  3. 2018.10.31 Mac下的Mysql修改字符编码修改的问题总结

    今天在弄数据库的时候发现存入中文汉字变成了问号,Mac跟windows处理方式不一样. show variables like '%char%'; 查看当前mysql的编码格式 也就是默认编码格式 + ...

  4. Android学习笔记_JNI hello world

    1.需要准备的工具,eclipse,cdt(c++)插件,cygwin(unix)和 android ndk. 在cygwin的etc目录下将ndk的路径引入到profile文件中,可以在cygwin ...

  5. Android学习笔记_18_Activity生命周期 及 跳转方式

    一.Activity有三个状态: 1.当它在屏幕前台时(位于当前任务堆栈的顶部),它是激活或运行状态.它就是响应用户操作的Activity. 2. 当它上面有另外一个Activity,使它失去了焦点但 ...

  6. Vue nodejs商城-地址模块

    一.地址列表渲染 ,则不可以点击. src/views/Cart.vue <a class="btn btn--red" v-bind:class="{'btn-- ...

  7. Flask—06-理解掌握flask数据模型(02)

    数据模型 模型关系 一对多(使用最多) 一:学生(Student) 需要添加反向引用 多:文章(Article) 需要添加外键关联 一对一 一:学生(Student),主表 需要添加反向引用,在一对多 ...

  8. Mongodb在window上启动

    MongoDB 是目前在IT行业非常流行的一种非关系型数据库(NoSql),其灵活的数据存储方式备受当前IT从业人员的青睐.这里主要讲如何在windows平台下安装MongoDB. 安装最新版本mon ...

  9. vue项目中使用vuex

    1.运行 cnpm i vuex -S 2.导入包 import Vuex from 'vuex' 3.注册vuex到vue中 Vue.use(vuex) 4. var store = new Vue ...

  10. 20181009noip HZ EZ 两校联考trade(优先队列,贪心)

    题面戳这里 思路: 裸的,贪心... 考场上写了一个数据分治(70ptsDP,30pts线段树优化贪心,GG了后30分) 这道题其实很简单的 我们看图: 我们在A时刻买一个东西,在B时刻卖出去,我们可 ...