控制反转(IOC)/依赖注入(DI)理解

我的学习笔记,来自Acodehtml

一、术语java

控制反转/反向控制,英文全称“Inversion of Control”,简称IoC。程序员

依赖注入,英文全称“Dependency Injection”,简称DI。数据库

 

听说是Martin Fowler对控制反转的原理进行了深刻的探索后,为控制反转起了个新的名字叫“依赖注入”。也就是说,这两个术语讲的是同一个事物。函数

 

二、控制反转的“奥义”学习

  “实现必须依赖抽象,而不是抽象依赖实现”。this

 

三、实例理解spa

  只看了控制反转的奥义,对于通常人来讲仍是难以理解,就比如一位功夫大师告诉咱们“无招胜有招”,资质平平的我仍是没法理解到大师们的话,因而就凌乱了...code

  下面,仍是经过实际的程序来理解一下控制反转。htm

假设场景:从SQL Server数据库中获取数据。

【普通方法】

通常人会这么写程序:

首先,实现一个对数据库进行各类操做的类SqlServerDataBase:

 1 /*
 2 *SqlServerDataBase.java
 3 **/
 4 
 5 public class SqlServerDataBase {
 6     
 7     /*
 8     *构造函数、数据库链接等操做对应的语句
 9     */
10 
11     //从SQL Server数据库中获取数据
12     public List getDataFromSqlServer() {
13         //获取数据的具体语句
14     }
15 }

而后,就能够在业务层经过对象的实例来获取须要的数据:

 1 /*
 2 *Business.java
 3 **/
 4 
 5 public class Business{
 6     private SqlServerDataBase db = new SqlServerDataBase();
 7 
 8     //从SQL Server数据库中获取数据
 9     public void getData() {
10         List list = db.getDataFromSqlServer();
11     }
12 
13 }

这么一看,感受代码写得很不错啊,完美地知足了需求。但是,某一天,决定要将数据库更换为MySQL,因而咱们历尽千辛万苦写的两个程序都不能用了,咱们须要重写下面的代码:

/*
*MySQLDataBase.java
**/

public class MySQLDataBase {
    
    /*
    *构造函数、数据库链接等操做对应的语句
    */

    //从MySQL数据库中获取数据
    public List getDataFromMySQL() {
        //获取数据的具体语句
    }
}

/*
*Business.java
**/

public class Business{
    private MySQLDataBase db = new MySQLDataBase();

    //从MySQL数据库中获取数据
    public void getData() {
        List list = db.getDataFromMySQL();
    }

}

咱们又费劲巴拉地写了上面的两个文件。这时,客户又决定要用Oracle做为数据!!!这时,估计你的心里是无比的崩溃的。为了毛爷爷,咱们忍了,再次写了新的程序。

当写了以Oracle为数据库的程序后,客户说要用MongoDB做为数据库!!!这时,感受不再要当程序员了。

 

总结:

  从上面的例子中能够看出,一旦客户的业务需求变了,咱们写的代码基本就白搭了,还要重写新的代码。这是为何呢?缘由是:Business类的中使用到了具体的数据库对应的类,一旦要使用的数据库改变了,Business中的代码也得跟着改啊(getDataFromSqlServer()->getDataFromMySQL()->...)。

 

教训:

  要实现一种代码能够屡次重复利用,不依赖于具体业务的代码,实现Business类的重用。这时,咱们想到了大神告诉咱们的控制反转的奥义“实现必须依赖抽象,而不是抽象依赖实现”。

 

【IoC方式实现】

一、首先,定义一个从数据库中获取数据的接口DataBase,做为一个接口,它里面只有方法的声明,此处咱们须要一个从数据库中获取数据的方法:getData()。

 1 /*
 2 *DataBase.java
 3 */
 4 
 5 public interface DataBase{
 6     //该方法用来获取数据
 7     public void getData();
 8 }

二、接着,此时客户要求采用SQL Server做为项目的数据库,那么就实现一个负责从SQL Server数据库中获取数据的类SqlServerDataBase:

 1 /*
 2 *SqlServerDataBase.java
 3 */
 4 
 5 public class SqlServerDataBase implements DataBase{
 6     //该方法用来获取数据
 7     public void getData() {
 8         //如下是具体从SQL Server数据库中取数据的代码
 9         ......
10     }
11 }

该类具体实现了从SQL Server数据库中获取数据的过程。

三、此时,业务须要从数据库中获取数据,实现业务类Business(注意该类的写法,很重要):

 1 /*
 2 *Business.java
 3 */
 4 
 5 public class Business {
 6     //针对接口DataBase定义变量
 7     private DataBase db;
 8 
 9     public void setDataBase(DataBase db) {
10         this.db=db;
11     }
12 
13     //根据注入的数据库类,从xxx数据库中获取数据
14     public void getData() {
15         db.getData();
16     }
17 }

注意的地方:

  (1)在第7行,定义了一个操做数据库的接口的变量db,并非依赖于具体实现的类的变量;

  (2)定义了setDataBase()方法,该方法实现了具体实现的数据库操做类的变量的注入;

  (3)getData()方法或根据实际注入的数据库类型获取数据。

总结:

  能够看出,该方法的实现是依赖于抽象,而非依赖于具体的实现,是否是想到了IoC的终极奥义“实现必须依赖抽象,而不是抽象依赖实现”。

四、经过3中的Business类,实现了代码的重用(我的感受,也就是对业务层也实现了“兼容性强的一种封装”,所以才实现了代码的重用),下面就看一下怎么根据具体的数据库类型来实现数据库的取数据:

 1 /*
 2 *TestBusiness.java
 3 */
 4 
 5 public class TestBusiness {
 6     private Business Business = new Business();
 7 
 8     //根据注入的数据库类,从SQL Server数据库中获取数据
 9     public void getData() {
10         business.setDataBase(new SqlServerDataBase());
11         business.getData();
12     }
13 }

在第10行中,咱们将SQL Server类的变量的注入到业务类Business中,也就实现了从SQL Server数据库中取数据的操做。此时,咱们就不再怕客户更换数据库了。

假设客户要采用MySQL做为数据库,那么,咱们须要作的只有两点:

(1)实现基于MySQL的取数据的类MySQLDataBase

 1 /*
 2 *MySQLDataBase.java
 3 */
 4 
 5 public class MySQLDataBase implements DataBase{
 6     //该方法用来获取数据
 7     public void getData() {
 8         //如下是具体从MySQL数据库中取数据的代码
 9         ......
10     }
11 }

(2)更改注入的数据库类型

 1 /*
 2 *TestBusiness.java
 3 */
 4 
 5 public class TestBusiness {
 6     private Business Business = new Business();
 7 
 8     //根据注入的数据库类,从MySQL数据库中获取数据
 9     public void getData() {
10         business.setDataBase(new MySQLDataBase());
11         business.getData();
12     }
13 }

咱们只须要更改第10行中药注入的数据库类型,就完成了全部的工做。

 

此时,再次理解下IoC的终极奥义:实现必须依赖抽象,而不是抽象依赖实现。(修炼的境界又提高了一层)

 

转载请注明出处:http://www.cnblogs.com/acode/p/5356686.html

相关文章
相关标签/搜索