通用(超級)工廠的建立以及通過工廠控制物件的建立次數
阿新 • • 發佈:2021-02-14
通用工廠
Java的核心是反射和介面,通用工廠不同於靜態工廠,具有高可用性。
public class BeanFactory { private BeanFactory(){}; public static Object getObject(String beanName) { Object obj = null; //1,反射載入class檔案,無需導包 try { Class<?>clazz = Class.forName(beanName); // 2,例項化物件 obj = clazz.getDeclaredConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); } // 3,返回物件 return obj; } // 通過class檔案來獲取物件 public static <T> T getObject(Class<T> clazz){ T ret =null; try { ret=(T)clazz.getDeclaredConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); } return ret; } }
這是簡單的通用工廠,如果要增加比較複雜的功能,比如說控制物件的建立次數,(有些物件,比如說UseService只需要一個即可,返回的是一個單例)。
什麼是單例:就是通過建立物件的方法建立的物件,一直是原來的那個物件,最直接的體現就是物件的地址相同。
什麼是多例:就是每次建立的物件都不一樣,體現在每次建立的物件的地址不同。
物件建立只有一次或者無數次!!!
通過工廠控制物件的建立次數
那麼將工廠進行修改,此時不太需要靜態方法,直接new更好,體現了工廠是重量級資源,修改程式碼如下:
package factory; import java.util.HashMap; import java.util.Map; public class BeanFactory { // 用來儲存已經建立過的物件 private Map<String,Object>maps; // 工廠建立的同時,內建map生效 public BeanFactory(){ maps = new HashMap<>(); }; protected Object getObject(String beanName) throws Exception { Object obj = null; //1,反射載入class檔案,無需導包 Class<?>clazz = Class.forName(beanName); // 2,例項化物件 obj = clazz.getDeclaredConstructor().newInstance(); // 3,返回物件 return obj; } // 通過class檔案來獲取物件 protected Object getObject(Class clazz) throws Exception { return clazz.getDeclaredConstructor().newInstance(); } protected boolean ifExist(Class clazz){ return maps.containsKey(clazz.getName()); } protected Object getExistObject(String name){ return maps.get(name); } /** * 因為此時工廠要控制物件的建立次數,所以,其他的建立物件的方法必須私有化 * @param clazz 需要傳入的class物件 * @param isSingleton 是否該物件只需要一個 * @return 返回物件 * @throws Exception 產生的異常 */ public Object getObject(Class clazz,boolean isSingleton) throws Exception { Object ret=null; String name = clazz.getName(); // if object already exists if(this.ifExist(clazz)){ if(isSingleton){ ret= this.getExistObject(name); }else{ ret = this.getObject(clazz); } }else{ if(isSingleton){ ret = this.getObject(clazz); maps.put(name,ret); }else{ ret = this.getObject(clazz); } } return ret; } //此時需要多個getObject方法的過載,在這裡就不一一列舉寫了。 public Object getObjectDefault(Class clazz) throws Exception { return this.getObject(clazz,true); } }
程式碼測試結果如下:
BeanFactory factory = new BeanFactory();
System.out.println(factory.getObjectDefault(User.class));
System.out.println(factory.getObject(User.class,true));
System.out.println(factory.getObject(User.class,false));
結果:
可以進行改進的地方:有一個通過過載的方法-通過名稱來得到物件。因為要想反射建立類,該名稱必須是全稱,而全稱非常長,書寫不方便,所以我們可以應用properties檔案來對名稱進行簡化。
通過Properties類(特殊的map,key=String=value),或者是ResourceBundle類。來對類名稱進行簡化處理。
這個工廠的建立是不是很熟悉,對,就是spring的超級工廠的一些簡化,這個簡化工廠已經實現了工廠的一部分核心功能。