天天看點

Spring中使用工廠模式解耦詳解

解耦 降低程式之間的耦合性

為什麼要降低程式之間的耦合性

**原因很簡單。當耦合度很高時,在代碼維護過程中修改一個地方會涉及到很多地方。如果耦合關系不是澄清修改期間,後果可能是災難性的,特别是對于有許多變化的項目需求和多人協作開發和維護,修改一個地方會導緻子產品的錯誤一直運作穩定,如果是嚴重的,将導緻一個惡性循環,問題永遠不能完全解決,開發和測試正與各種各樣的問題作鬥争。最終會導緻項目延遲,降低使用者滿意度,增加成本。而且也提高了程式的複用性

引入類之間的耦合性

在我們學習jdbc通路資料庫時,具體流程是

首先在maven裡面導入依賴

<packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>      

然後就是jdbc的實作過程:

1.注冊驅動

2.擷取連接配接

3.擷取操作資料庫的預處理對象

4.執行SQL,得到結果集

5.周遊結果集

6.釋放資源

具體代碼如下:

public class Jdbc {
    public static void main(String[] args) throws  Exception{
        //1.注冊驅動
    //  DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Class.forName("com.mysql.jdbc.Driver");

        //2.擷取連接配接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","1234");
        //3.擷取操作資料庫的預處理對象
        PreparedStatement pstm = conn.prepareStatement("select * from account");
        //4.執行SQL,得到結果集
        ResultSet rs = pstm.executeQuery();
        //5.周遊結果集
        while(rs.next()){
            System.out.println(rs.getString("name"));
        }
        //6.釋放資源
        rs.close();
        pstm.close();
        conn.close();
    }
}      

第一種建立驅動方式

進行分析,上面代碼中被注釋的那句代碼

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

如果把pom裡面的依賴注釋就相當于沒有jar包,然後我們進行編譯

則不能編譯,會是一個錯誤,如圖所示:

Spring中使用工廠模式解耦詳解

第二種建立驅動方式

Class.forName(“com.mysql.jdbc.Driver”);

這句代碼就隻依賴于一個字元串而不是一個驅動類。

這樣子當jar包不存在時,就是一個異常而不是一個錯誤。這樣子就是避免的類之間的耦合性

Spring中使用工廠模式解耦詳解

但是産生一個新的問題,導緻這個字元串在類中寫死了如果換成其他資料庫的話,就還要改代碼,是以我們要通過配置檔案來擷取要建立的對象全限定類名,然後再用反射來建立對象

是以 解耦的思路:

第一步:使用反射來建立對象,而避免使用new關鍵字。

第二步:通過讀取配置檔案來擷取要建立的對象全限定類名

實際開發中:

應該做到:編譯期不依賴,運作時才依賴。

業務層Service調用持久層Dao時的耦合性

Dao層

userdao層的接口

public interface IUserDao {
    void save();
}      

userdao層的實作類

package Dao.IMPL;

import Dao.IUserDao;

public class UserDao implements IUserDao {

    public void save() {
        System.out.println("hello");
    }
}
      

UserService的接口

package Service;
public interface IUserService {
    void save();
}      

UserService的實作類

package Service.IMPL;
import Dao.IMPL.UserDao;
import Service.IUserService;
public class UserService implements IUserService {
    //private将這個對象私有化
    //因為dao是一個接口的實作類  接口是不是執行個體化的 但是可以建立一個接口的實作類對象
    private IUserDaodao=new UserDao();
    public void save() {
        System.out.println("hello");
    }
}      

private IUserDaodao=new UserDao(); 這句代碼就是Service層調用Dao層,當我們把UserDao的代碼去除之後,程式就出現報錯,不能編譯成功,說明程式之間的耦合性太強了。

工廠模式解耦合

上面的service層調用dao層的耦合性太強之後我們可以參考之前的jdbc裡面的步驟。

第一步:使用反射來建立對象,而避免使用new關鍵字。
 第二步:通過讀取配置檔案來擷取要建立的對象全限定類名      

是以我們可以通過工廠來進行一個解耦

BeanFactory:個建立Bean對象的工廠

什麼是Bean

在計算機英語中,有可重用元件的含義,可重用的意思是一個servlet可能有多個service 一個service中可能有多個dao.一個servicc或者一個dao都是一個Bean.

第一步:需要一個配置檔案來配置我們的service和dao 配置的内容:唯一辨別=全限定類名(key=value)

我們建立一個Bean.properties也可以是一個Bean.xml,在這裡我們在resources裡面建立一個Bean.properties記錄裡面的全限定類名

UserService=Service.IMPL.UserService
UserDao=Dao.IMPL.UserDao      

第二步通過讀取配置檔案中配置的内容,反射建立對象

package factory;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class BeanFactory {

    //讀取配置檔案
    //定義一個靜态Properties對象
    private static Properties props;
//    //定義一個Map,用于存放我們要建立的對象。我們把它稱之為容器
    //多例變單例
    private static Map<String,Object> beans;
    //使用靜态代碼塊為Properties對象指派
    static {
        try {
            //執行個體化對象
            props = new Properties();
            //擷取properties檔案的流對象
            //這個時候不能用new FileInputStream因為這這個時候的相對路肩和絕對路徑都不管用
            //we工程部署src沒有了   相對路徑不能用 絕對路徑也不行
            //要用類加載器來進行操作
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            //加載一個流對象
            props.load(in);
//            //執行個體化容器
            beans = new HashMap<String,Object>();
//            //取出配置檔案中所有的Key
            Enumeration keys = props.keys();
//            //周遊枚舉
            while (keys.hasMoreElements()){
//                //取出每個Key
                String key = keys.nextElement().toString();
//                //根據key擷取value
                String beanPath = props.getProperty(key);
//                //反射建立對象
                Object value = Class.forName(beanPath).newInstance();
//                //把key和value存入容器中
                beans.put(key,value);
            }
        }catch(Exception e){
            //抛出一個初始化錯誤  後面直接執行不了
            throw new ExceptionInInitializerError("初始化properties失敗!");
        }
    }
    /**
     * 根據bean的名稱擷取對象  用Object類型做傳回值
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }      

這樣之後,我們再調用dao層時就可以把在BeanFactory裡面建立

private IUserDao dao= (IUserDao) BeanFactory.getBean("UserDao");      
IUserService service= (IUserService) BeanFactory.getBean("UserService");      

新建立一個公衆号 Rockey小何同學 想互相交流的同學可以關注一下哈! 感謝支援!