Inversion of Control(控制反转)之 Dependency Injection(依赖注入)
随着项目复杂度的提高,程序模块与模块间的关系犹如一碗意大利面。高耦合的代码会越来越难维护。所以松耦合的代码设计,会随着项目复杂度的提高而越来来越明显。
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(依赖注入)相关推荐
- 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )
文章目录 前言 一.创建 事件监听器 对应的 动态代理 二.动态代理 数据准备 三.动态代理 调用处理程序 四.动态代理 实例对象创建 前言 Android 依赖注入的核心就是通过反射获取 类 / 方 ...
- 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 获取要注入事件的 View 对象 | 通过反射获取 View 组件的事件设置方法 )
文章目录 前言 一.获取要注入事件的 View 对象 二.通过反射获取 View 组件的事件设置方法并执行 前言 Android 依赖注入的核心就是通过反射获取 类 / 方法 / 字段 上的注解 , ...
- 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 获取 Activity 中的所有方法 | 获取方法上的注解 | 获取注解上的注解 | 通过注解属性获取事件信息 )
文章目录 前言 一.获取 Activity 中的所有方法 二.获取方法上的注解 三.获取注解上的注解 四.通过注解属性获取相关事件信息 前言 Android 依赖注入的核心就是通过反射获取 类 / 方 ...
- 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入代码示例 )
文章目录 总结 一.Android 事件依赖注入示例 1.创建依赖注入库 2.声明注解 (1).修饰注解的注解 (2).修饰方法的注解 3.Activity 基类 4.动态代理类调用处理程序 5.依赖 ...
- 【IOC 控制反转】Android 视图依赖注入 ( 视图依赖注入步骤 | 视图依赖注入代码示例 )
文章目录 总结 一.Android 视图依赖注入步骤 二.Android 布局依赖注入示例 1.创建依赖注入库 2.声明注解 3.Activity 基类 4.依赖注入工具类 5.客户端 Activit ...
- IoC(Inversion of Control,控制反转)模式
IoC模式 1.依赖依赖就是有联系,有地方使用到它就是有依赖它,一个系统不可能完全避免依赖.如果你的一个类或者模块在项目中没有用到它,恭喜你,可以从项目中剔除它或者排除它了,因为没有一个地方会依赖它. ...
- IoC容器和 Dependency Injection模式 Inversion of Control Containers and the Dependency Injection pattern
原文链接:http://www.martinfowler.com/articles/injection.html 文末有中文翻译版本,martinfowler上有提供中文版的pdf,也可以自行下载 中 ...
- 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 ...
- 【IOC 控制反转】IOC 简介 ( 依赖注入的两种实现方式 | 编译期注入 | 运行期注入 )
文章目录 一.IOC 简介 二.依赖注入的两种实现方式 一.IOC 简介 IOC 是 Inversion Of Control 的缩写 , 控制反转 ; 其最主要的作用是 降低代码的耦合度 , 最常见 ...
- 【SSM框架系列】Spring IoC(控制反转) DI(依赖注入)
Spring是什么 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Orie ...
最新文章
- 研究人员利用非线性原理为机器人创造出类似昆虫的步态,脑机接口也可以使用...
- 从csv文件批量创建AD用户,带源码。
- 在Asp.net应用程序中构建基于WCF Web.Api的服务
- 前端参数无法转为后端实体内部类_Java学到什么程度才能叫精通?
- HTML5事件—visibilitychange 页面可见性改变事件
- webservices系列(二)——JAX-WS文件上传下载
- 未捕获typeerror: $形象。cropper不是函数_没有学不会的python--细说自定义函数的细节...
- 员工为什么缺乏执行力?
- optional 解决空指针_Java8新特性:Optional类的正确使用姿势
- [MetalKit]7-Using-MetalKit-part-6使用MetalKit6
- 数据结构与算法 第二章 数据结构中的线性结构
- React Native之原理浅析, iOS原理分析与实践解析、Android原理分析与实践解析
- ubuntu安装PYQT4
- 马云、奥巴马都上当:“女版乔布斯”600亿惊天骗局,电影都不敢这么拍
- 双绞线的制作方式详解
- 浅谈计算机教学的现状分析,浅谈中职计算机专业教学的现状与对策
- 微信模板消息发送成功但显示空白的问题
- 网络安全学习路线-超详细
- 字典(dict),增删改查,嵌套
- CPT101-小豪的笔记
热门文章
- 基于Linux命令行终端的ftp客户端程序
- ES6新语法 变量 、 服务器端js和浏览器端js的区别
- C++ 多继承之如何调用私有成员
- HTML-HTML基本语法和标签
- auto static 的区别
- 基于顺序存储结构的图书信息表的修改(C++)
- java mathrandom函数_java Math数学工具及Random随机函数
- 使用Kubeadm搭建Kubernetes(1.12.2)集群
- yii2 刷新缓存(刷新模型缓存)
- 20172316 结对编程-四则运算 第一周 阶段总结