控制反轉 IOC 理論推導
控制反轉 IOC 理論推導
按照我們傳統的開發,我們會先去 dao 層建立一個介面,在介面中定義方法。
public interface UserDao {
void getUser();
}
然後再去實現類中實現這個方法的作用。
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("預設獲取使用者的資料");
}
}
然後再去 service 層寫一個介面,在介面中定義方法。
public interface UserService { void getUser(); }
再然後寫實現類,實現裡面的方法。
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
然後我們使用這業務類
public class MyTest { public static void main(String[] args) { // 使用者實際呼叫的是業務層,dao 層他們不需要接觸 UserService userService = new UserServiceImpl(); userService.getUser(); } }
最後會輸出
預設獲取使用者的資料
但是現在在 dao 層新增加了一個實現,例如 UserDaomySql
public class UserDaoMysql implements UserDao {
@Override
public void getUser() {
System.out.println("從 MySQL 中獲取資料");
}
}
如果我們想要從 UserDaoMysql 這個類中呼叫 getUser() 這個方法,就需要在 UserServiceImpl 這個類中修改程式碼,將建立的 UserDaoImpl 改為 UserMysqlImpl 這個物件。然後才能得到我們想要的效果。
從 MySQL 中獲取資料
如果使用者就像產品經理一樣,今天要你想要在 UserDaoImpl 這個物件中獲取資料,明天就想要從 UserDaoMysql 這個物件中獲取資料呢?
我們面對這樣的問題,是不是還要每次去修改程式碼,如果我們在很多地方建立了這個物件,豈不是要到處修改,或者有更多的實現類,產品經理又突然叫我們用另一個物件,這樣我們就會被折磨死。是吧!
我們都知道猴子的臉說變就變,產品經理何嘗不是?
那麼我們可以不可以這樣做,我們就吧選擇權交給產品經理,我們不按照我們的意願去建立這個物件,我們將這個問題拋給產品經理,誒,我不建,我讓他去選,他喜歡用哪個,那就建立哪個。
我們來看看我們在 UserServiceImpl 中建立物件的那條語句
private UserDao userDao = new UserDaoImpl();
我想聰明的你,看到這條語句你就很快能明白,這個不就是定義一個物件變數,然後建立一個物件,將其賦值給它。
那麼我們可不可以想個辦法,讓他動態的將這個物件注入到這個變數裡面呢?
聰明的你仔細想想,想想我們建立實體類的時候。
嘿嘿!!!
是不是想到了什麼。
我們建立實體類的時候,是不是一開始我們沒有為那個變數賦值,是後面才用 Set 賦值的吧。
所以是不是想到該怎麼做了,嘿嘿嘿
沒錯,我們就是寫個 Setter
private UserDao userDao;
/**
* 利用 Set 進行動態實現值的注入
* @param userDao dao 層的物件
*/
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
我寫的和你想的一樣嗎?我想是的吧。
然後我們使用它
public class MyTest {
public static void main(String[] args) {
// 使用者實際呼叫的是業務層,dao 層他們不需要接觸
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoMysql());
userService.getUser();
}
}
這樣我們是不是就可以隨便產品經理怎麼想了,他愛用啥用啥,讓他自己選一個建立就好了。
這樣我們是不是就實現了反轉,誒,我不建立物件,讓你來選,你喜歡哪一個,就用哪一個。