存在的目的:
解耦,在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