定義一個用於建立對象的接口,讓子類決定實例化哪個類,工廠方法使一個類的實例化延遲到其子類。java
基本工廠方法模式數據庫
抽象產品類服務器
public abstract class AbstractProduct { // 公共方法 public void methodOne() { // 業務邏輯 } // 抽象方法 public abstract void methodTwo(); }
具體產品類,都繼承自抽象產品類網絡
public class ConcreteProductOne extends AbstractProduct { public void methodTwo() { // 業務邏輯 } } public class ConcreteProductTwo extends AbstractProduct { public void methodTwo() { // 業務邏輯 } }
抽象工廠類,負責定義產品對象的產生框架
public abstract class AbstractProductFactory { // 建立一個產品對象,參數類型一般爲 String, Enum, Class public abstract <T extends AbstractProduct> T createProduct(Class<T> c); }
具體工廠類,繼承抽象工廠類設計
public class ProductFactory extends AbstractProductFactory { // 建立一個產品對象,參數類型一般爲 String, Enum, Class public <T extends AbstractProduct> T createProduct(Class<T> c) { AbstractProduct abstractProduct = null; try { abstractProduct = (AbstractProduct) Class.forName(c.getName()).newInstance(); } catch (Exception exception) { // 異常處理 } return abstractProduct; } }
場景類code
public class Client { public static void main(String[] args) { AbstractProductFactory productFactory = new ProductFactory(); AbstractProduct productOne = productFactory.createProduct(ConcreteProductOne.class); AbstractProduct productTwo = productFactory.createProduct(ConcreteProductTwo.class); // TODO } }
new
一個對象的替代品,在全部須要生成對象的地方均可以使用,,但須要謹慎考慮是否須要增長一個工廠類進行管理,增長代碼的複雜度工廠方法模式有多種擴展,並且與其它模式結合使用使用威力更大對象
假如一個模塊僅須要一個工廠類,沒有必要把它產生出來,使用靜態方法便可繼承
去掉抽象工廠類,將工廠方法設置爲靜態方法接口
public class ProductFactory { // 建立一個產品對象,參數類型一般爲 String, Enum, Class public static <T extends AbstractProduct> T createProduct(Class<T> c) { AbstractProduct abstractProduct = null; try { abstractProduct = (AbstractProduct) Class.forName(c.getName()).newInstance(); } catch (Exception exception) { // 異常處理 } return abstractProduct; } }
一個產品類有多個實現類,且每個實現類的初始化還須要爲對象設置必定的初始值,若是將全部的產品類放到一個工廠方法中進行初始化,一定會致使該工廠方法巨大無比,且代碼結構不清晰。所以,須要爲每個產品定義一個工廠類。
多工廠模式抽象工廠類
public abstract class AbstractProductFactory { // 不須要爲工廠方法傳遞參數,每個具體的工廠方法職責明確 public abstract AbstractProduct createProduct(); }
不一樣產品的工廠類,繼承抽象工廠類
public class ProductOneFactory extends AbstractProductFactory { public AbstractProduct createProduct() { return new ConcreteProductOne(); } } public class ProductTwoFactory extends AbstractProductFactory { public AbstractProduct createProduct() { return new ConcreteProductTwo(); } }
優勢:建立類的職責清晰,結構簡單
缺點:可擴展性及可維護性差。擴展產品類須要創建相應的工廠類,增長擴展難度及維護成本
使用工廠方法模式實現單例模式
單例類
public class Singleton { private Singleton() {} public void doSomething() { // TODO } }
負責生成單例的工廠類,使用反射方式生成單例對象
public class SingletonFactory { private static Singleton singleton; static { try { Class clazz = Class.forName(Singleton.class.getName()); // 獲取無參構造器 Constructor constructor = clazz.getDeclaredConstructor(); // 設置無參構造器可訪問 constructor.setAccessible(true); // 產生一個實例對象 singleton = (Singleton) constructor.newInstance(); } catch (Exception exception) { // 異常處理 } } public static Singleton getSingletonInstance() { return singleton; } }
經過得到類構造器,設置訪問權限,生成一個對象,而後提供外部訪問,保證內存中的對象惟一。經過工廠方法模式建立一個單例對象,該框架能夠繼續擴展,在一個項目中產生一個單例構造器,全部須要產生單例的類遵循必定的規則(構造器私有化),只須要輸入一個類型可得到惟一的一個實例。
一個對象被消費完畢後,並不當即釋放,工廠類保持其初始狀態。
延遲加載的工廠類
public class ProductFactory { private static final Map<String, AbstractProduct> prMap = new HashMap(); public static synchronized AbstractProduct createProduct(String type) throws Exception { AbstractProduct product = null; if (prMap.containsKey(type)) { product = prMap.get(type); } else { if (type.equals("one")) { product = new ConcreteProductOne(); } else { product = new ConcreteProductTwo(); } prMap.put(type, product); } return product; } }
經過定義一個Map
容器,容納全部產生的對象,若在Map容器中已經有的對象直接取出返回,若是沒有,根據須要的類型產生一個對象,並放入到Map容器中,方便下次調用。
延遲加載框架可擴展爲限制某一產品類的最大實例化數量,經過判斷Map容器中已有的對象數量來實現。如JDBC鏈接數據庫,都會要求設置一個maxConnections
最大鏈接數量,該數量就是內存中的最大實例化數量。