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. SPOJ MUSKET - Musketeers

    黑书P117页. 要是不看解析,确实不要算和定义状态. 把环看成链,是指把这个1234512345,写两边,然后怎么表示一个人是否胜利了呢?其实就是其他人全部死光(好像等于没说): 考虑最后一次杀人, ...

  2. python+requests实现接口测试 - get与post请求使用

    简介:Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 ...

  3. 三角测量(Triangulation)

    三角测量(Triangulation)是视觉定位中,已知多个相机位置和空间中一点的投影点,进一步求该点3D位置的方法.三角测量是Pose Estimation的相反过程,求出相机位置后,图像中其它特征 ...

  4. Extjs 4 动态显示折线图 按秒显示

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  5. 菜鸟笔记 -- Chapter 6 面向对象

    在Java语言中经常被提到的两个词汇是类与对象,实质上可以将类看作是对象的载体,它定义了对象所具有的功能.学习Java语言必须要掌握类与对象,这样可以从深层次去理解Java这种面向对象语言的开发理念, ...

  6. 利用pt-query-digest分析MySQL慢查询

    1.用法与参数说明 pt-query-digest [OPTIONS] [FILES] [DSN] --create-review-table ##当使用--review参数把分析结果输出到表中时,如 ...

  7. vue.esm.js:578 [Vue warn]: Missing required prop

    问题: 解决: required: true,属性是,这个必须填写

  8. 动态规划(一)POJ1163

    动态规划算法是比较实用的算法之一,结合实际问题能更好的熟悉这个算法 下面以POJ1163为例子 1. 首先是题目大意 :在给定的一个数字三角形中找到一条自上而下的路径,路径每一步只能左下或者右下,最后 ...

  9. ABAP术语-Business Connector

    Business Connector 原文:http://www.cnblogs.com/qiangsheng/archive/2007/12/27/1016379.html XML-based st ...

  10. 配置django控制台输出ORM转化的sql

    在setting中配置 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ ' ...