簡單的例子解釋IOC控制反轉進行解耦合
一、相關概念
(1)解耦合
解耦合就是把程序中互相不相關或有限相關的模塊分割開來,把不同模塊互相之間的關系用接口進行準確定義,解耦前,兩個模塊之間共享所有信息;
(2)作用
解耦后,需要共享的信息唄準確地定義在接口中,并確定信息的流向,解耦合可以令程序變得清晰,把不該暴露的實現細節隱藏,使代碼的修改簡單化,同時使程序結構靈活,通過靜態多態或動態多態,一個模塊可以和任意實現接口的模塊協作,系統擴展性大大增強。消除編譯依賴,調試也相應簡易,只要模塊對一個接口調試成功,其他的接口也將沒有問題
(3)控制反轉
① 軟件系統在沒有引入IoC容器之前,對象A依賴對象B,那么A對象在實例化或者運行到某一點的時候,自己必須主動創建對象B或者使用已經創建好的對象B,其中不管是創建還是使用已創建的對象B,控制權都在我們自己手上。
②如果軟件系統引入了Ioc容器之后,對象A和對象B之間失去了直接聯系,所以,當對象A實例化和運行時,如果需要對象B的話,IoC容器會主動創建一個對象B注入到對象A所需要的地方。
③ 通過前面①②的對比,可以看到對象A獲得依賴對象B的過程,由主動行為變成了被動行為,即把創建對象交給了IoC容器處理,控制權顛倒過來了,這就是控制反轉的由來!
注:在控制反轉與解耦過程中使用了設計模式中的工廠模式。
(4)工廠模式
工廠模式是指當應用程序中甲組件需要乙組件協助時,并不是在甲組件中直接實例化乙組件對象,而是通過乙組件的工廠獲取,即該工廠可以生成某一類型組件的實例對象。在這種模式下,甲組件無需與乙組件以硬編碼的方式耦合在一起,而只需與乙組件的工廠耦合
二、Spring底層中使用了IOC的模式,此處用程序簡單的介紹其原理
(1)xml文件(beans.xml),用于存儲DAO,Service層的具體實現類名稱以及class所在權限路徑
代碼如下:
<xml-body>
<beans><bean id="ProductService" class="com.itheima.service.impl.ProductServiceImpl"></bean><bean id="UserService" class="com.itheima.service.impl.UserServiceImpl"></bean><bean id="CategoryService" class="com.itheima.service.impl.CategoryServiceImpl"></bean><bean id="OrderService" class="com.itheima.service.impl.OrderServiceImpl"></bean><bean id="ProductDao" class="com.itheima.dao.impl.ProductDaoImpl"></bean><bean id="UserDao" class="com.itheima.dao.impl.UserDaoImpl"></bean><bean id="CategoryDao" class="com.itheima.dao.impl.CategoryDaoImpl"></bean><bean id="OrderDao" class="com.itheima.dao.impl.OrderDaoImpl"></bean>
</beans>
</xml-body>
(2)工廠類(BeanFactory),運用反射的原理實例化對象
此處反射機制需要導入”dom4j-1.6.1.jar“jar包,代碼如下:
package com.itheima.utils;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;public class BeanFactory {
public static Object getBean(String id)
{try {//獲取document對象Document doc=new SAXReader().read(BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml"));//獲取指定的bean對象Element ele= (Element) doc.selectSingleNode("//bean[@id='"+id+"']");//獲取bean對象的class屬性String value=ele.attributeValue("class");//反射return Class.forName(value).newInstance();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;
}public static void main(String[] args)
{System.out.println(getBean("OrderDao"));System.out.println(getBean("OrderService"));
}
}
(3)View層中,實現注入
此處為手動注入,即調用BeanFactory返回實例化對象,代碼如下:
ProductService ps=(ProductService) BeanFactory.getBean("ProductService");
(4)在main函數中驗證
mainpublic static void main(String[] args)
{
System.out.println(getBean("OrderDao"));
System.out.println(getBean("OrderService"));
}
三、總結
通過工廠類的控制反轉,在改變DAO層不同的應用方法(比如jdbc轉化為hibernate框架)時,無需更改代碼,只需更該配置文件的class名稱及class的路徑