一天一個設計模式:簡單工廠模式

存在的目的:

  解耦,在a類中如何想使用b類的某種功能,必須new 一個b對象出來,假如有一個c類,跟b實現了同一個接口,後續想要將b替換成c就需要更改在a中的代碼,以此類推,代碼的耦合度會隨着項目複雜度越來越高,維護成本也會越來越高。

  使用簡單工廠,使a類與工廠做耦合,然後工廠來提供接口的實現類即可,這樣只需要對工廠進行維護就可以實現替換了成功解耦。

核心思想:

  不在乎工廠是如何生產產品的,而是將產品的生產與產品的使用分開。        注:這裏的產品指的是功能類的對象

實際的應用:

  jdk中的線程池:ThreadPoolExecutor,根據自己的需求傳入corePoolSize、maximumPoolSize、keepAliveTimem、keepAliveTimem、unit、threadFactory、handler這幾個參數,new一個指定的ThreadPoolExecutor出來。

  jdk提供了Executors這個類,讓開發者對線程池的使用與生產分離開,開發者只需要調用不同的方法就可以獲取到不同的線程池,開發者不用關心線程池的實現細節,只需要調用api即可獲取不同的線程池。

      如:Executors.newSingleThreadExecutor()        獲取單線程的線程池              Executors.newCachedThreadPool()        獲取無界線程池

優點:     簡單優化了軟件體系結構,明確了各自功能模塊的職責和權力,     通過工廠類,外界不需要直接創建具體產品對象,只需要負責消費,不需要關心內部如何創建對象。 缺點:     如果只是使用簡單的if else這樣來做生產,隨着產品的增多,勢必要對工廠類進行不斷的維護,     使用反射的工廠效率會低一些。

實現案例

以登錄系統爲例,支持多種登錄體系:口令登錄、域登錄。那麼需要建立一個各種登錄方式都適合的接口,uml圖如下:

登錄接口:

public interface Login {
    //登錄驗證
    public boolean verify(String name , String password);
}

域登錄:

public class DomainLogin implements Login {

    @Override
    public boolean verify(String name, String password) {
        // TODO Auto-generated method stub
        /**
         * 業務邏輯
         */
        return true;
    }

}

口令登錄:

public class PasswordLogin implements Login {

    @Override
    public boolean verify(String name, String password) {
        // TODO Auto-generated method stub
        /**
         * 業務邏輯
         */
        return true;
    }

}

工廠類LoginManager,根據需求創建對象,如果不合法就跑出異常,會返回一個Runtime異常

public class LoginManager {
    public static Login factory(String type){
        if(type.equals("password")){
            
            return new PasswordLogin();
            
        }else if(type.equals("passcode")){
            
            return new DomainLogin();
            
        }else{
            /**
             * 這裏拋出一個自定義異常會更恰當
             */
            throw new RuntimeException("沒有找到登錄類型");
        }
    }
}

測試類:

public class Test {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String loginType = "password";
        String name = "name";
        String password = "password";
        Login login = LoginManager.factory(loginType);
        boolean bool = login.verify(name, password);
        if (bool) {
            /**
             * 業務邏輯
             */
        } else {
            /**
             * 業務邏輯
             */
        }
    }
}

實際上的結構圖:

基於上面的,使用反射來實現

public class LoginManager {
    public static Login factory(String path) {
        Class<?> c = Class.forName(fruitPath);
        return (Fruit)c.newInstance();
    }   
}

這樣僅需要控制入參就可以獲取對應的實例了,不需要那麼多if else了結構上更加清爽。

 參考鏈接:

https://www.cnblogs.com/java-my-life/archive/2012/03/22/2412308.html

https://www.cnblogs.com/xrq730/p/4902597.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章