---
# System prepended metadata

title: IOC理論
tags: [Spring-IOC]

---

# IOC理論
###### tags: `Spring-IOC`

### 原先的代碼寫法
範例：
1.UserDao DAO接口
2.UserDaoImpl實現類
3.UserService業務接口
4.UserServiceImpl 業務實現類

我們透過UserServiceImpl來實現業務需求
```java=
public class UserServiceImpl implements UserService{
    
    private UserDao userDao = new UserDaoImpl();
    
    public void getUser(){
        userDao.getUser();
    }
}
```

如果用戶要調用
```java=
public class MyTest{
    public static void main(String[] args){
        
        //用戶調用的是業務層，dao層它們不需要接觸
        UserService userService = new UserServiceImpl();
        //調用UserDaoImpl中的方法
        userService.getUser();
    }
}
```

如果今天新創建一個新Dao實現類，例如UserDaoMysqlImpl
```java=
public class UserDaoMysqlImpl implements UserDao{
    public void getUser(){
        System.out.println("Mysql獲取用戶數據");
    }
}
```

按照原先作法，我們必須改寫業務實現類的代碼
```java=
public class UserServiceImpl implements UserService{
    //從原先創建UserDaoImpl對象，改成UserDaoMysqlImpl對象
    private UserDao userDao = new UserDaoMysqlImpl();
    
    public void getUser(){
        userDao.getUser();
    }
}
```

#### 壞處：在於每次創建新的Dao實現類，要引用它時，就必須重寫一遍相關代碼，既費時又麻煩

### 改善作法：

```java=
public class UserServiceImpl implements UserService{
    
    private UserDao userDao;
    //利用set進行對態實現值的注入
    public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }
    
    public void getUser(){
        userDao.getUser();
    }
}
```

```java=
public class MyTest{
    public static void main(String[] args){
        
        UserService userService = new UserServiceImpl();
        //可以讓用戶自行決定要調用哪個實現類，不用再改動底層代碼
        ((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl);
        
        userService.getUser();
    }
}
```

#### 之前的業務中，用戶的需求可能會影響我們原來的代碼，我們需要根據用戶的需求去修改原代碼，如果程序代碼量十分大，修改一次的成本代價十分昂貴 

#### 我們使用一個set接口實現，已經發生了革命性的變化
```java=
private UserDao userDao;
    //利用set進行對態實現值的注入
public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }
```

#### 之前，程序是主動創建對象，控制權在程序員手上
#### 使用set注入後，程序不再具有主動性，而是變成了被動的接受對象

### 這種思想，從本質上解決了問題，程序員不用再去管理對象的創建，系統的耦合性大幅降低，可以更加專注在業務的實現，這是IOC的原型

***********
### 舊的方式：主動權在業務層
![](https://i.imgur.com/ZbgCl1o.png)

### 新的方法：主動權在用戶
![](https://i.imgur.com/KJEB3gX.png)

## IOC的本質
**控制反轉IOC(Inversion of Control)**，是一種設計思想，DI(依賴注入)是實現IOC的一種方法，也有人認為DI只是IOC的另一種說法。沒有IOC的程序中，我們使用面向對象編程，對象的創建與對象間的依賴關係完全硬編碼在程序中，對象的創建由程序自己控制，控制反轉後將對象的創建轉移到第三方，個人認為控制反轉就是，**獲得依賴對象的方式反轉了**

控制反轉是一種透過描述(XML或注解)，並透過第三方去生產或獲取特定對象的方式，在Spring中實現控制反轉的是IOC容器，其實現方式是依賴注入(Dependency Injection,DI)

### 早期作法：耦合性強
![](https://i.imgur.com/U1KyMVH.png)

### 優化：加入IOC，降低耦合性，達到解耦效果
![](https://i.imgur.com/mKKZymk.png)
