控制反转IoC简介
控制反转IoC简介
在实际的应用开发中,我们需要尽量避免和降低对象间的依赖关系,即降低耦合度。通常的业务对象之间都是互相依赖的,业务对象与业务对象、业务对象与持久层、业务对象与各种资源之间都存在这样或那样的依赖关系。但是如何才能做到降低类之间的依赖关系呢?这就是本文核心IoC需要解决的问题,下面从两大点具体介绍IoC:
(1)IoC与DI的基本概念
IoC(Inversion Of Control)即控制反转,其具体就是由容器来控制业务对象之间的依赖关系,而不是像传统方式中由代码来直接控制。控制反转的本质,是控制权由应用代码转到了外部容器,控制权的转移即是所谓的反转。控制权的转移带来的好处就是降低了业务对象之间的依赖程度,即实现了解耦。
IoC的实现策略有两种:
1)依赖查找:容器中的受控对象通过容器的API来查找自己所依赖的资源和协作对象。这种方式虽然降低了对象间的依赖,但是同时也使用到了容器的API,造成了我们无法在容器外使用和测试对象;
2)依赖注入(又称DI:Dependency Injection):对象只提供普通的方法让容器去决定依赖关系,容器全权负责组建的装配,它会把符合依赖关系的对象通过属性或者是构造函数传递给需要的对象。通过属性注射依赖关系的做法称为设值方法注入,将构造子参数传入的做法称为构造子注入。
依赖注入的好处如下:
查询依赖操作和应用代码分离;
受控对象不会使用到容器的特定的API,这样我们的受控对象可以搬出容器单独使用。
(2)IoC模式的实例讲解
IoC代表的是一种思想,也是一种开发模式,但它不是什么具体的开发方法。要理解IoC的概念,最简单的方式就是看它的实际应用,下面将着重介绍几个实例来讲解IoC的内涵。
我们在开发一个应用系统时,会需要开发大量的Java类,系统将会通过这些Java类之间的相互调用来产生作用。类与类之间的调用关系是系统类之间最直接的关系。因此,我们可以将系统中的类分为两类:调用者和被调用者。具体如下图一所示:
图一:调用方法问题
软件设计方法及设计模式的发展,共产生了三种类调用的方法:自己创建(new)、工厂模式(get)、外部注入(set),其中外部注入即为IoC/DI的模式。
无论是哪一种方法,都存在两个角色——调用者和被调用者。下面我们通过实例来讲解这三种方法的具体含义。首先,我们设定调用者对象为学生对象Student,被调用者对象为图书对象Book,要设计的代码功能是学生学习图书知识。
从GoF设计模式中,我们已经习惯一种思维编程方式:Interface Driven Design接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等。为了演示不同的方法在Student取得不同Book对象时的区别,我们采用接口来设计被调用者,实现的代码如下面三个类所示:
//Book接口类
public interface IBook{
public void learn();
}
//BookA实现类
public class BookA implements IBook{
public void learn(){
System.out.println("学习BookA");
}
}
//BookB实现类
public class BookB implements IBook{
public void learn(){
System.out.println("学习BookB");
}
}
其中IBook为图书的接口,它定义了一个学习接口learn(),并定义了两个图书类BookA和BookB来实现该接口,表示是两本不同的图书,其中learn()方法分别表示不同图书学习过程。
下面将从这三种方法讲解如何调用图书类:
1)new——自己创建
Student要学习BookA,就要定义一个learnBookA()的方法,并自己来创建BookA的对象;同样,要学习BookB,就要定义一个learnBookB()的方法,并自己来创建BookB的对象。然后我们建立一个测试类Test.java来创建一个Student对象,可以分别调用learnBookA()和learnBookB()方法来分别执行两本书的学习过程。具体实现代码如下:
//学生类
public class Student{
public void learnBookA(){
IBook book = new BookA();
book.learn();
}
public void learnBookB(){
IBook book = new BookB();
book.learn();
}
}
//测试运行
public class Test{
public static void main(){
Student student = new Student();
student.learnBookA();
student.learnBookB();
}
}
该方法在调用者Student需要调用被调用者IBook时,需要由自己创建一个IBook对象。这种做法的缺点是,无法更换被调用者,并且要负责被调用者的整个生命周期。具体形式如下图二所示:
图二:自己创建方式
2)get——工厂模式
一切对象都由自己创建的缺点是,每一次调用都需要自己来负责创建对象,创建的对象会到处分散,造成管理上的麻烦,比如异常处理等。因此,我们可以将对象创建的过程提取出来,由一个工厂(Factory)统一来创建,需要什么对象都可以从工厂中取得。
例如下例中,我们创建了一个工厂类BookFactory,为该类添加两个函数getBookA()和getBookB(),分别用于创建BookA和BookB的对象。然后再创建Student中learnBookA()和learnBookB()中的方法,改为分别在该工厂类中取得这两个对象。具体实现代码如下;
//图书工厂
public class BookFactory{
public static IBook getBookA(){
IBook book = new BookA();
}
public static IBook getBookB(){
IBook book = new BookB();
}
}
//学生类
public class Student{
public void learnBookA(){
IBook book = BookFactory.getBookA();
book.learn();
}
public void learnBookB(){
IBook book = BookFactory.getBookB();
book.learn();
}
}
//测试运行
public class Test{
public static void main(){
Student student = new Student();
student.learnBookA();
student.learnBookB();
}
}
此时与第一种方法的区别是,多了一个工厂类,并将Student中创建对象的代码提取到了工厂类,Student直接从工厂类中取得要创建的对象。这种方法的优点是,实现了对象的统一创建,调用者无须关心对象创建的过程,只管从工厂中取得即可。具体形式如下图三所示:
图三:工厂模式
这种方法实现了一定程度的优化,使得代码的逻辑也更趋向于统一。但是,对象的创建依然不灵活,因为对象的取得完成取决于工厂,又多了中间一道工序。
3)set——外部注入
显然,第一种方式依赖于被调用者对象,第二种方式依赖于工厂,都存在依赖性。为了彻底解决依赖性的问题,我们又取消了工厂类,并仅仅为Student添加一个学习的方法learnBook(),输入的参数是接口类型IBook。在使用Student的方法时,我们先创建IBook的具体对象,然后再把该对象作为learnBook()的输入参数注入到Student,调用接口IBook的统一方法learn()即可完成学习过程。具体实现代码如下所示:
//学生类
public class Student{
public void learnBook(IBook book){
book.learn();
}
}
//测试运行
public class Test{
public static void main(){
IBook bookA = new BookA();
IBook bookB = new BookB();
Student student = new Student();
student.learnBook(bookA);
student.learnBook(bookB);
}
}
这样我们完全简化了Student类的方法,learnBook()的方法不再依赖于某一个特定的Book,而是使用了接口类IBook,这样只要在外部创建任意IBook的实现对象输入到该方法即可,使得Student类完全解脱了与具体某一种Book的依赖关系。上例中的Test.java,分别创建了bookA和bookB对象,同样都可以调用Student的learnBook()方法,使得Student变得完全通用。具体形式如下图四所示:
图四:外部注入方式
可见,set——外部注入方式完全抛开了依赖关系的枷锁,可以自由的由外部注入,这就是IoC,将对象的创建个获取提前到外部,由外部容器提供需要的组件。
控制反转IoC简介的更多相关文章
- 浅析“依赖注入(DI)/控制反转(IOC)”的实现思路
开始学习Spring的时候,对依赖注入(DI)——也叫控制反转(IOC)—— 的理解不是很深刻.随着学习的深入,也逐渐有了自己的认识,在此记录,也希望能帮助其他入门同学更深入地理解Spring.本文不 ...
- 控制反转IOC的依赖注入方式
引言: 项目中遇到关于IOC的一些内容,因为和正常的逻辑代码比较起来,IOC有点反常.因此本文记录IOC的一些基础知识,并附有相应的简单实例,而在实际项目中再复杂的应用也只是在基本应用的基础上扩展而来 ...
- 控制反转IOC与依赖注入DI
理解 IOC http://www.cnblogs.com/zhangchenliang/archive/2013/01/08/2850970.html IOC 相关实例 的http:// ...
- 控制反转(Ioc)和依赖注入(DI)
控制反转IOC, 全称 “Inversion of Control”.依赖注入DI, 全称 “Dependency Injection”. 面向的问题:软件开发中,为了降低模块间.类间的耦合度,提倡基 ...
- 控制反转IOC与依赖注入DI【转】
转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...
- 依赖注入(DI)和控制反转(IOC)
依赖注入(DI)和控制反转(IOC) 0X1 什么是依赖注入 依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只 ...
- iOS控制反转(IoC)与依赖注入(DI)的实现
背景 最近接触了一段时间的SpringMVC,对其控制反转(IoC)和依赖注入(DI)印象深刻,此后便一直在思考如何使用OC语言较好的实现这两个功能.Java语言自带的注解特性为IoC和DI带来了极大 ...
- 个人对【依赖倒置(DIP)】、【控制反转(IOC)】、【依赖注入(DI)】浅显理解
一.依赖倒置(Dependency Inversion Principle) 依赖倒置是面向对象设计领域的一种软件设计原则.(其他的设计原则还有:单一职责原则.开放封闭原则.里式替换原则.接口分离原则 ...
- 【转载】浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI)
原文地址 http://blog.csdn.net/briblue/article/details/75093382 写这篇文章的原因是这两天在编写关于 Dagger2 主题的博文时,花了大量的精力来 ...
随机推荐
- jquery如何判断checkbox(复选框)是否被选中 ...
<script type="text/javascript" src="../lib/jQuery1.11.1.js"></script> ...
- processModel与ASP.NET进程模型
配置 Microsoft Internet 信息服务 (IIS) Web 服务器上的 ASP.NET 进程模型设置.其作用是配置IIS或IIS中的应用程序池(IIS7及以后版本)的安全性,性能,健壮性 ...
- JS检查是否支持Storage
查看效果:http://hovertree.com/code/html5/q69kvsi6.htm 代码: <!DOCTYPE html> <html> <head> ...
- 疯狂Android讲义 - 学习笔记(六)
第7章 7.1 使用简单图片 7.1.1 使用Drawable对象 7.1.2 Bitmap和BitmapFactory 7.2 绘图 7.2.1 Android绘图基础:Canvas.Paint等 ...
- KMP算法-next函数求解
KMP函数求解:一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为KMP算法.KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串 ...
- [moka同学笔记]五、Yii2.0课程笔记(魏曦老师教程)[审核功能]
- Verilog HDL模型的不同抽象级别
所谓不同的抽象类别,实际上是指同一个物理电路,可以在不同层次上用Verilog语言来描述.如果只从行为功能的角度来描述某一电路模块,就称作行为模块.如果从电路结构的角度来描述该电路模块,就称作结构模块 ...
- git 常用指令
下载项目 git clone https://git.oschina.net/jianqingwang/jianblog.git 注意,clone跟的是项目地址 查看分支(也就是版本) git bra ...
- linux top命令查看内存及多核CPU的使用讲述
查看多核CPU命令 mpstat -P ALL 和 sar -P ALL 说明:sar -P ALL > aaa.txt 重定向输出内容到文件 aaa.txt top命令 经常用来监控l ...
- Xdebug文档(四)函数跟踪
Xdebug能让你把所有函数调用,包括参数和返回值以不同的格式记录到文件中. 这些号称“函数跟踪”功能能帮助你面对一个新应用程序,亦或者在程序运行时你想弄清楚它在做什么.函数跟踪功能可以选择性地显示函 ...