1. 程式人生 > >理解Spring IOC概念及如何降低程式碼耦合度

理解Spring IOC概念及如何降低程式碼耦合度

什麼是IOC

IOC(Inversion of Control) 控制反轉,是spring中一個重要的特性,是面向物件程式設計中的一種設計原則,可以用來減低計算機程式碼之間的耦合度。那麼控制什麼的的權利被反轉了呢,我們知道在寫程式碼的過程中,經常會出現兩個物件之間出現依賴關係,當A物件依賴B物件時,我們通常在A物件中通過new的方式來建立它的依賴物件B,而控制反轉之後,對於物件的建立權被託付給IOC容器了,也就是這些物件由容器來產生,而不是物件在需要的時候再去建立自己的依賴物件。

舉例來理解IOC,一個家庭的組建需要夫妻兩個,某種意義上,我們可以說兩者之間存在依賴關係。傳統方式就是,當我需要組建一個家庭時,我自己去找物件,自己去組建家庭,而IOC方式就是將找物件的權利委託給爸爸媽媽,當我一出生時,爸爸媽媽就為我指腹為婚,為我找好了物件。

IOC如何降低了程式碼之間的耦合度

從傳統方式到IOC一步步解耦

第一步轉變 直接new物件---->面向介面程式設計

最開始我們建立一個物件是採取new物件的方式,但這樣不可以實現多型,比如我建立一個person物件,裡面有一個eat(Apple apple)方法,那麼呼叫這個eat方法的類,需要傳入蘋果(Apple)物件,之後我的這個方法改成吃梨子了,這個方法又改成eat(Pear pear)了,呼叫eat方法的類,又需要把之前的蘋果改成梨子,擴充套件性差,於是出現了面向介面程式設計,我在eat方法裡面傳入水果(Fruit)介面,之後蘋果,梨只需要實現介面即可,呼叫eat方法的類,想吃梨子就傳入梨子,想吃蘋果傳入蘋果即可。

第二步轉變 面向介面程式設計 -----> 工廠模式

面向介面程式設計後,解決介面和實現類之間的耦合 在面向介面程式設計中我們常常會出現這樣的程式碼UserDao userDao = new UserDaoImpl(); 假設現在不用這個UserDaoImpl了,而改用UserDao的另一個實現類UserDaoImpl2,UserDao userDao = new UserDaoImpl()需要改為UserDao userDao = new UserDaoImpl2(),這樣也就是介面和實現類出現了耦合。

工廠模式如何去解決耦合問題呢 ---- 不讓介面和實現類產生關係,而是找一箇中間人,也就是工廠,實現類必須要從工廠中取出來。工廠的意思也就是一個批量製造同樣規格(規格也就是介面類所提供好的規範)類的類。 工廠類:

class BeanFactory {
    public static UserDao getUserDao() {
        return new UserDaoImpl();
    }
    public static StudentDao getStudentDao() {
        return new StudentDaoImpl();
    }
}

UserDao userDao = new UserDaoImpl —> UserDao userDao = BeanFacotry.getUserDao(); StudentDao studentDao = new StudentDaoImpl ----> StudentDao studentDao = BeanFacotry.getStudentDao(); 這樣的話,如果userDao變成了需要UserDaoImpl1,studentDao變成了需要StudentDaoImpl1,我只需要去BeanFactory中改對應的getUserDao和getStudentDao方法即可。這樣實際上就是從改多個類變成了改BeanFacotry一個方法,這樣介面類和工廠類產生了耦合。

第三步轉變 工廠模式 ----> 工廠模式+反射+配置檔案(IOC的底層實現)

為了能解決介面類和工廠類的耦合,是不是也就是要解決

public static UserDao getUserDao() {
    return new UserDaoImp();
}

這個方法中只能返回UserDaoImpl或者UserDaoImpl1的問題,我們希望他可以根據我們的需要返回需要的UserDaoImpl,如何解決? 配置xml檔案 — 指定需要返回的UserDaoImpl

<bean id="userDao" class="**.UserDaoImpl">

工廠類

class BeanFactory {
    public static UserDao getUserDao(String id) {
        // String className = 解析配置檔案xml 拿到id對應的class
        // 反射
        class clazz = class.forName(className);
        return clazz.newInstance();
    }
}

這樣的話如果我們需要改UserDao的實現類的型別,我們可以直接在配置檔案中修改,就不用改程式碼啦!

Spring中DI概念

DI:依賴注入,前提是必須要有IOC的環境,Spring管理這個類的時候將類依賴的屬性注入進來 我們在寫程式碼的時候知道,物件和物件之間經常會存在依賴關係,當我們使用了IOC將物件的建立權交給spring之後,spring在建立物件的同時一定也要將物件相應的依賴同時建立好,否則建立的這個物件就是一個功能不完善的物件,那麼依賴注入的這個過程就是它的另一個特性DI(依賴注入)