不可不知的DIP、IoC、DI以及IoC容器
面向对象设计(OOD)有助于我们开发出高性能、易扩展以及易复用的程序。当中。OOD有一个重要的思想那就是依赖倒置原则(DIP),并由此引申出IoC、DI以及Ioc容器等概念。
本文首先用实例阐述四个概念。而且给出Java版本号的演示样例代码。
依赖倒置原则(DIP)
依赖倒置是一种软件架构设计的原则,。依赖倒置原则,它转换了依赖,高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口。通俗的讲,就是高层模块定义接口,低层模块负责实现。
怎样理解呢?举例说明吧。
先看生活中的一个样例。
图1 ATM与银行卡
相信大部分取过钱的朋友都深有感触,仅仅要有一张卡,随便到哪一家银行的ATM都能取钱。在这个场景中。ATM相当于高层模块,而银行卡相当于低层模块。ATM定义了一个插口(接口),供全部的银行卡插入使用。也就是说,ATM不依赖于详细的哪种银行卡。
它仅仅需定义好银行卡的规格參数(接口)。全部实现了这样的规格參数的银行卡都能在ATM上使用。现实生活如此,软件开发更是如此。
依赖倒置(高层模块定义接口,低层模块负责实现)
在这个图中,我们发现高层模块定义了接口,将不再直接依赖于低层模块。低层模块负责实现高层模块定义的接口。
这样,当有新的低层模块实现时,不须要改动高层模块的代码。
由此。我们能够总结出使用DIP的长处:
系统更柔韧:能够改动一部分代码而不影响其它模块。
系统更健壮:能够改动一部分代码而不会让系统崩溃。
系统更高效:组件松耦合。且可复用,提高开发效率。
控制反转(IoC)
DIP是一种 软件设计原则,它只告诉你两个模块之间应该怎样依赖,可是它并没有告诉怎样做。IoC则是一种 软件设计模式,它告诉你应该怎样做,来解除相互依赖模块的耦合。控制反转(IoC),它为相互依赖的组件提供抽象,将依赖(低层模块)对象的获得交给第三方(系统)来控制。即依赖对象不在被依赖模块的类中直接通过new来获取。
依赖注入(DI)
控制反转(IoC)一种重要的方式。就是将依赖对象的创建和绑定转移到被依赖对象类的外部来实现。主要实现有三种方式:构造函数注入;属性注入;接口注入。
以下以将订单存储到数据库为例,用Java演示样例来说明问题。
如果系统开发初期使用SqlServer。我们简历数据库操作类。
public class SqlServer {
public void add(){
System.out.println("Addorder to Sql Server!");
}
}
定义一个order类:
public class Order {
private SqlServer ss=newSqlServer();
public void add(){
ss.add();
}
}
測试一下:
public class Main {
public static void main(String[]args) {
Order o=new Order();
o.add();
}
}
输出:
到这里没问题,可是假设须要加入MySql的数据库呢?
这里须要建立操作MySql的数据库类:
public class MySql {
public void add(){
System.out.println("Add to mysqlServer");
}
}
订单类须要改动:
public class Order {
private MySql ss=new MySql();
public void add(){
ss.add();
}
}
測试输出:
假设还须要很多其它的数据库操作呢?这样下去还需改动代码。组件之间高度耦合,可扩展性较差,它违背了DIP原则。
依赖注入就是解决上述问题。
依赖注入主要有三种实现方式:构造函数注入;属性注入;接口注入。以下用演示样例进行说明。
1、 构造函数
构造函数函数注入。毫无疑问通过构造函数传递依赖。因此,构造函数的參数必定用来接收一个依赖对象。那么參数的类型是什么呢?详细依赖对象的类型?还是一个抽象类型?依据DIP原则,我们知道高层模块不应该依赖于低层模块。两者应该依赖于抽象。那么构造函数的參数应该是一个抽象类型。
定义接口:
public interface IDB {
publicvoid add();
}
然后在SqlServer中实现这个接口
publicclass SqlServer implements IDB{
@Override
public void add() {
// TODO Auto-generatedmethod stub
System.out.println("Addinto Sql Server");
}
}
改动order类,在构造函数中注入对象:
public class Order {
private IDB idb;
public Order(IDB idb){
this.idb=idb;
}
public void add(){
this.idb.add();
}
}
測试类:
public class Main {
publicstatic void main(String[] args) {
IDBidb=new SqlServer();
Ordero=new Order(idb);
o.add();
}
}
输出:
通过构造函数注入的方式我们将依赖对象SqlServer的创建和绑定转移到了Order类的外部来实现。这样就解除了SqlServe和Order类的讴歌关系。当我们须要换成MySql数据库的时候。仅仅须要又一次定义一个Mysql类实现IDB接口,在用到的地方新建。在Order的外部又一次绑定依赖。不须要改动Order的代码。
比如:
新建MySql类:
public class MySql implements IDB{
@Override
publicvoid add() {
//TODO Auto-generated method stub
System.out.println("Addinto MySql server!");
}
}
在Main函数中仅仅须要需改:
IDB idb=new MySql();
測试:
2、 属性注入
属性注入是通过属性来传递依赖。
因此,我们首先须要在依赖类Order中定义一个属性。
public class Order{
private IDB idb;//私有属性
public void add(){
this.idb.add();
}
public IDB getIdb() {
return idb;
}
public void setIdb(IDB idb) {
this.idb = idb;//接受依赖
}
}
接口类以及数据库訪问类同上。Main方法须要这么写:
public class Main{
public static void main(String[] args) {
IDB idb=new SqlServer();
Order o=new Order();
o.setIdb(idb);
o.add();
}
}
測试输出:
Add into SqlServer
假设须要扩展MySql数据库。仅仅须要在Main方法里改动为:
IDBidb=newMySql();
測试输出:
Add into MySql
3、 接口注入
相比构造函数注入和属性注入。接口注入显得有些复杂,使用也不常见。详细思路是先定义一个接口。包括一个设置依赖的方法。然后依赖类。继承并实现这个接口。
首先定义一个接口:
public interface IDependent {
publicvoid setDependency(IDB idb);
}
依赖类实现这个接口:
public class Order implements IDependent{
privateIDB idb;
@Override
publicvoid setDependency(IDB idb) {
//TODO Auto-generated method stub
this.idb=idb;
}
publicvoid add(){
this.idb.add();
}
}
还须要定义数据库訪问的接口:
public interface IDB {
publicvoid add();
}
详细数据库的实现须要实现这个接口:
public class SqlServer implements IDB{
@Override
publicvoid add() {
//TODO Auto-generated method stub
System.out.println("Addinto Sql Server");
}
}
測试类:
public class Main {
publicstatic void main(String[] args) {
Ordero=new Order();
IDBidb=new SqlServer();
o.setDependency(idb);
o.add();
}
}
測试输出:
Add into SqlServer
假设须要加入MySql的訪问须要定义MySql的实现:
public class MySql implements IDB{
@Override
publicvoid add() {
//TODO Auto-generated method stub
System.out.println("Addinto MySql");
}
}
在測试类仅仅须要作例如以下改动就可以:
IDBidb=newMySql();
測试输出:
Add into MySql。
IoC容器
简单的来讲就是抛弃手动的方式创建依赖对象传递给被依赖模块而选取DI框架替我们创建来减轻我们的工作量。对于大型项目来说,相互依赖的组件比較多。假设还用手动的方式。自己来创建和注入依赖的话,显然效率非常低,并且往往还会出现不可控的场面。正因如此。IoC容器诞生了。IoC容器实际上是一个DI框架,它能简化我们的工作量。它包括下面几个功能:
l 动态创建、注入依赖对象。
l 管理对象生命周期。
l 映射依赖关系。
Java中比較突出的就是Spring了。很多其它Spring的介绍将出如今后面的博文里。
不可不知的DIP、IoC、DI以及IoC容器的更多相关文章
- Atitit。如何实现dip, di ,ioc ,Service Locator的区别于联系
Atitit.如何实现dip, di ,ioc ,Service Locator的区别于联系 1. Dip原则又来自于松耦合思想方向1 2. 要实现dip原则,有以下俩个模式1 3. Ioc和di的 ...
- dip vs di vs ioc
https://stackoverflow.com/questions/6766056/dip-vs-di-vs-ioc https://docs.microsoft.com/en-us/aspnet ...
- Spring4学习回顾之路02—IOC&DI
IOC&DI介绍 ●IOC:(Inversion of Control) :控制反转(反向获取资源) 其思想是反转资源获取的方向.传统的资源上查找方式要求组件向容器发起请求查找资源,作为回应, ...
- 深入理解DIP、IoC、DI以及IoC容器
摘要 面向对象设计(OOD)有助于我们开发出高性能.易扩展以及易复用的程序.其中,OOD有一个重要的思想那就是依赖倒置原则(DIP),并由此引申出IoC.DI以及Ioc容器等概念.通过本文我们将一起学 ...
- 对依赖倒置原则(DIP)及Ioc、DI、Ioc容器的一些理解
1.概述 所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模 ...
- 深入理解DIP、IoC、DI以及IoC容器(转)
深入理解DIP.IoC.DI以及IoC容器 摘要 面向对象设计(OOD)有助于我们开发出高性能.易扩展以及易复用的程序.其中,OOD有一个重要的思想那就是依赖倒置原则(DIP),并由此引申出IoC.D ...
- 【转】深入理解DIP、IoC、DI以及IoC容器
原文链接:http://www.cnblogs.com/liuhaorain/p/3747470.html 前言 对于大部分小菜来说,当听到大牛们高谈DIP.IoC.DI以及IoC容器等名词时,有没有 ...
- 对依赖倒置原则(DIP)及Ioc、DI、Ioc容器的一些理解(转)
所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合 ...
- DIP、IoC、DI以及IoC容器
深入理解DIP.IoC.DI以及IoC容器 摘要 面向对象设计(OOD)有助于我们开发出高性能.易扩展以及易复用的程序.其中,OOD有一个重要的思想那就是依赖倒置原则(DIP),并由此引申出IoC.D ...
随机推荐
- 细节!重点!易错点!--面试java基础篇(一)
今天来给大家分享一下java的重点易错点部分,也是各位同学面试需要准备的,欢迎大家交流指正. 1.java中的main方法是静态方法,即方法中的代码是存储在静态存储区的. 2.任何静态代码块都会在ma ...
- Microsoft Visual C++运行库合集下载(静默安装)
Microsoft Visual C++运行库合集下载 CN启示录2013-06-02上传 Microsoft Visual C++运行库合集由国外网友McRip制作,包含了VC2005.VC20 ...
- Windows下实战Apache+PHP [转]
一.Apache 1.下载登陆Apache Lougne(http://www.apachelounge.com/download/),找到最新版本的Apache.笔者下载的是带IPv6和Cr ...
- WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性
原文 WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性 如果您在使用WPF/Silverlight进行相关动画开发中使用了Storyboard,并对关联属性进 ...
- GreenDao数据库结构升级
1.先用GreenDao工具类编写自动创建代码,按照升级后的最新数据库结构来编写 2.GreenDao工具自动生成的代码覆盖到项目里去 3.在项目里找到对应的自动生成的数据库DaoMaster类 在D ...
- innerXml,outerXml,innerText的不同
原文:innerXml,outerXml,innerText的不同 昨天看到咱们园子里有一个仁兄写的关于xml的有关操作,在读的过程中,由于是初学者有不明白的地方就查资料,发现自己多innerXml, ...
- 拍照图片滤镜sample
本文章主要介绍拍完照片后对图片的渲染进行处理 可以对拍出的照片进行选择不同的滤镜,令在图片上附有编辑框,供大家对图片进行描述,这是一个可以手动拖动的编辑框,在这里主要介绍下,手指放到控件上什么情况下视 ...
- C# MVC 自学笔记—2 MVC Movie简介
MVC Movie是微软官方的一个MVC入门项目,我们可以跟着这个项目来实践入门 这是官方地址 http://www.asp.net/mvc/tutorials/mvc-4/getting-start ...
- android 实现代码关机
开始从网上搜索,通过发action的方式实现,不过一直没有成功. Intent intent = new Intent(); intent.setAction(Intent.ACTION_SHUT ...
- Delphi事件的广播 good
明天就是五一节了,辛苦了好几个月,借此机会应该尽情放松一番.可是想到Blog好久没有写文章,似乎缺些什么似的.这几个月来在项目中又增长了许多经验,学到许多实际应用的知识.不如把一些比较有用的记录下来, ...