FactoryMethodPattern工廠方法模式

工廠方法模式

1.定義

定義一個用於建立對象的接口,讓子類決定實例化哪個類,工廠方法使一個類的實例化延遲到其子類。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
    }
}

2.應用

2.1 優勢

  • 良好的封裝性,代碼結構清晰,一個對象的建立具備條件的約束
  • 擴展性很是優秀,在增長產品的狀況下,只適當修改工廠類或擴展一個工廠類
  • 屏蔽產品類,調用者不須要關心產品類如何變化,只須要關注產品接口保持不變
  • 工廠方法模式是典型的解耦框架。高層模塊只須要知道產品抽象類,不用關心其它實現類

2.2 使用場景

  • 工廠方法模式是new一個對象的替代品,在全部須要生成對象的地方均可以使用,,但須要謹慎考慮是否須要增長一個工廠類進行管理,增長代碼的複雜度
  • 須要靈活可擴展的框架時,能夠考慮採用工廠方法模式。萬物皆對象,萬物也皆產品類。如須要設計一個鏈接郵件服務器的框架,有三種網絡協議可供選擇:POP3,IMPA,HTTP,能夠將這三種鏈接方法做爲產品類,定義一個鏈接接口,使用不一樣的方法實現具體的產品類,再定義一個工廠方法,根據不一樣的條件選擇不一樣的鏈接方式。若增長新的鏈接方式,只須要增長新的產品類便可。

3.擴展

工廠方法模式有多種擴展,並且與其它模式結合使用使用威力更大對象

3.1 簡單工廠模式(靜態工廠模式)

假如一個模塊僅須要一個工廠類,沒有必要把它產生出來,使用靜態方法便可繼承

去掉抽象工廠類,將工廠方法設置爲靜態方法接口

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;
    }
}

3.2 多工廠模式

一個產品類有多個實現類,且每個實現類的初始化還須要爲對象設置必定的初始值,若是將全部的產品類放到一個工廠方法中進行初始化,一定會致使該工廠方法巨大無比,且代碼結構不清晰。所以,須要爲每個產品定義一個工廠類。

多工廠模式抽象工廠類

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();
    }
}

優勢:建立類的職責清晰,結構簡單

缺點:可擴展性及可維護性差。擴展產品類須要創建相應的工廠類,增長擴展難度及維護成本

3.3 替代單例模式

使用工廠方法模式實現單例模式

單例類

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;
    }
}

經過得到類構造器,設置訪問權限,生成一個對象,而後提供外部訪問,保證內存中的對象惟一。經過工廠方法模式建立一個單例對象,該框架能夠繼續擴展,在一個項目中產生一個單例構造器,全部須要產生單例的類遵循必定的規則(構造器私有化),只須要輸入一個類型可得到惟一的一個實例。

3.4 延遲初始化

一個對象被消費完畢後,並不當即釋放,工廠類保持其初始狀態。

延遲加載的工廠類

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最大鏈接數量,該數量就是內存中的最大實例化數量。

相關文章
相關標籤/搜索