随着项目复杂度的提高,程序模块与模块间的关系犹如一碗意大利面。高耦合的代码会越来越难维护。所以松耦合的代码设计,会随着项目复杂度的提高而越来来越明显。

GoF说过,依赖倒置原则:高层模块不应该依赖地层模块,它们都应依赖于抽象;
抽象不依赖于细节,细节依赖抽象;

下面是一个没有依赖注入容器的情况下实现依赖注入:`public class Email

public class Email
{public void SendEmail(){// code}
}public class Notification
{private Email _email;public Notification(){_email = new Email();}public void PromotionalNotification(){_email.SendEmail();}
}

Notification类依赖Email类,这违反了DIP,而且当我们要发送短信/保存到数据库的时候,我们还要改变Notification类。
我们使用抽象类/接口解耦

public interface IMessageService
{void SendMessage();
}
public class Email : IMessageService
{public void SendMessage(){// code}
}
public class Notification
{private IMessageService _iMessageService;public Notification(){_iMessageService = new Email();}public void PromotionalNotification(){_iMessageService.SendMessage();}
}

IMessageService 是一个接口,而Notification 类只要调用接口的方法/属性就可以了
同时,我们把Email对象的构造移到Notification 类外面去。

依赖注入模式可以实现。通常有三种方式
1. 构造器注入
2. 属性注入
3. 方法注入

构造器注入
最普遍的方式,当一个类需要另一个类的依赖的时候,我们通过构造函数来提供,现在我们这样写

public class Notification
{private IMessageService _iMessageService;public Notification(IMessageService _messageService){this._iMessageService = _messageService;}public void PromotionalNotification(){_iMessageService.SendMessage();}
}

有几个好处:1.构造函数实现很简单,Notification类需要知道的很少。想要创建Notification实例的时候看构造函数就可以知道需要什么信息了。因此实现了松耦合。

属性注入

属性注入/setter注入比较不常见,当依赖可有可无的时候很有用。我们暴露一个可写的属性,允许客户提供不同的依赖实现,比如这样。

public class Notification
{public IMessageService MessageService{get;set;}public void PromotionalNotification(){if (MessageService == null){// some error message}else{MessageService.SendMessage();}}
}

没有了构造函数。而用属性来替换,在PromotionalNotifications 方法里我们需要检查MessageService的值或者提供相应的服务。

方法注入
当依赖可以对于每个方法调用都不同的时候,我们可以通过一个方法参数来实现,比如我们的这个类还可以发送短信。我们就要使用方法注入

public class Email : IMessageService
{public void SendMessage(){// code for the mail send}
}
public class SMS : IMessageService
{public void SendMessage(){// code for the sms send}
}public class Notification
{public void PromotionalNotification(IMessageService _messageService){_messageService.SendMessage();}
}

IMessageService 接口在两个类中都实现了。我们可以提供不同的类对象作为参数,这样可以有不同的调用效果。我们可以使用这三种方法实现松耦合。取决于具体的情景

Inversion of Control(控制反转)之 Dependency Injection(依赖注入)相关推荐

  1. 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )

    文章目录 前言 一.创建 事件监听器 对应的 动态代理 二.动态代理 数据准备 三.动态代理 调用处理程序 四.动态代理 实例对象创建 前言 Android 依赖注入的核心就是通过反射获取 类 / 方 ...

  2. 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 获取要注入事件的 View 对象 | 通过反射获取 View 组件的事件设置方法 )

    文章目录 前言 一.获取要注入事件的 View 对象 二.通过反射获取 View 组件的事件设置方法并执行 前言 Android 依赖注入的核心就是通过反射获取 类 / 方法 / 字段 上的注解 , ...

  3. 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 获取 Activity 中的所有方法 | 获取方法上的注解 | 获取注解上的注解 | 通过注解属性获取事件信息 )

    文章目录 前言 一.获取 Activity 中的所有方法 二.获取方法上的注解 三.获取注解上的注解 四.通过注解属性获取相关事件信息 前言 Android 依赖注入的核心就是通过反射获取 类 / 方 ...

  4. 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入代码示例 )

    文章目录 总结 一.Android 事件依赖注入示例 1.创建依赖注入库 2.声明注解 (1).修饰注解的注解 (2).修饰方法的注解 3.Activity 基类 4.动态代理类调用处理程序 5.依赖 ...

  5. 【IOC 控制反转】Android 视图依赖注入 ( 视图依赖注入步骤 | 视图依赖注入代码示例 )

    文章目录 总结 一.Android 视图依赖注入步骤 二.Android 布局依赖注入示例 1.创建依赖注入库 2.声明注解 3.Activity 基类 4.依赖注入工具类 5.客户端 Activit ...

  6. IoC(Inversion of Control,控制反转)模式

    IoC模式 1.依赖依赖就是有联系,有地方使用到它就是有依赖它,一个系统不可能完全避免依赖.如果你的一个类或者模块在项目中没有用到它,恭喜你,可以从项目中剔除它或者排除它了,因为没有一个地方会依赖它. ...

  7. IoC容器和 Dependency Injection模式 Inversion of Control Containers and the Dependency Injection pattern

    原文链接:http://www.martinfowler.com/articles/injection.html 文末有中文翻译版本,martinfowler上有提供中文版的pdf,也可以自行下载 中 ...

  8. Inversion of Control Containers and the Dependency Injection pattern--Martin Fowler

    原文地址:https://martinfowler.com/articles/injection.html n the Java community there's been a rush of li ...

  9. 【IOC 控制反转】IOC 简介 ( 依赖注入的两种实现方式 | 编译期注入 | 运行期注入 )

    文章目录 一.IOC 简介 二.依赖注入的两种实现方式 一.IOC 简介 IOC 是 Inversion Of Control 的缩写 , 控制反转 ; 其最主要的作用是 降低代码的耦合度 , 最常见 ...

  10. 【SSM框架系列】Spring IoC(控制反转) DI(依赖注入)

    Spring是什么 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Orie ...

最新文章

  1. 研究人员利用非线性原理为机器人创造出类似昆虫的步态,脑机接口也可以使用...
  2. 从csv文件批量创建AD用户,带源码。
  3. 在Asp.net应用程序中构建基于WCF Web.Api的服务
  4. 前端参数无法转为后端实体内部类_Java学到什么程度才能叫精通?
  5. HTML5事件—visibilitychange 页面可见性改变事件
  6. webservices系列(二)——JAX-WS文件上传下载
  7. 未捕获typeerror: $形象。cropper不是函数_没有学不会的python--细说自定义函数的细节...
  8. 员工为什么缺乏执行力?
  9. optional 解决空指针_Java8新特性:Optional类的正确使用姿势
  10. [MetalKit]7-Using-MetalKit-part-6使用MetalKit6
  11. 数据结构与算法 第二章 数据结构中的线性结构
  12. React Native之原理浅析, iOS原理分析与实践解析、Android原理分析与实践解析
  13. ubuntu安装PYQT4
  14. 马云、奥巴马都上当:“女版乔布斯”600亿惊天骗局,电影都不敢这么拍
  15. 双绞线的制作方式详解
  16. 浅谈计算机教学的现状分析,浅谈中职计算机专业教学的现状与对策
  17. 微信模板消息发送成功但显示空白的问题
  18. 网络安全学习路线-超详细
  19. 字典(dict),增删改查,嵌套
  20. CPT101-小豪的笔记

热门文章

  1. 基于Linux命令行终端的ftp客户端程序
  2. ES6新语法 变量 、 服务器端js和浏览器端js的区别
  3. C++ 多继承之如何调用私有成员
  4. HTML-HTML基本语法和标签
  5. auto static 的区别
  6. 基于顺序存储结构的图书信息表的修改(C++)
  7. java mathrandom函数_java Math数学工具及Random随机函数
  8. 使用Kubeadm搭建Kubernetes(1.12.2)集群
  9. yii2 刷新缓存(刷新模型缓存)
  10. 20172316 结对编程-四则运算 第一周 阶段总结