導讀
- 工廠方法模式是所有設計模式中比較常用的一種模式,但是真正能搞懂用好的少之又少,Spring底層大量的使用該設計模式來進行封裝,以致開發者閱讀源代碼的時候暈頭轉向。
- 文章首發於微信公眾號【碼猿技術專欄】,原創不易,謝謝支持!!!
- 今天陳某分別從以下五個方面詳細講述一下工廠方法模式:
- 「從什么是工廠方法模式」
- 「通用框架實現」
- 「工廠方法模式的優點」
- 「工廠方法模式的升級」
- 「Spring底層如何使用工廠方法模式」
什么是工廠方法模式?
- 定義:定義一個用於創建對象的 接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。

- 在工廠方法模式中,抽象產品
Product
負責定義產品的特性,實現對事物的抽象定義。
AbstractFactory
是抽象工廠類,定義了一個抽象工廠方法。具體的如何創建產品由工廠實現類ConcreteFactory
完成。
通用框架實現
- 工廠方法模式的變種有很多,陳某給出一個比較實用的通用框架。
抽象產品類
:
public abstract class Product { /** * 公共邏輯方法 */
public void method1(){} /** * 抽象方法:由子類實現,根據業務邏輯定義多個 */
public abstract void method2(); }
public class Product1 extends Product { /** * 實現抽象產品類的抽象方法 */ @Override public void method2() { } }
public class Product2 extends Product { /** * 實現抽象產品類的抽象方法 */ @Override public void method2() { } }
抽象工廠類
,必須定義一個工廠方法來自己實現具體的創建邏輯,如下:
public abstract class AbstractFactory { /** * 工廠方法,需要子類實現 * @param cls * @param <T> * @return */
public abstract <T extends Product> T create(Class<T> cls); }
public class ConcreteFactory extends AbstractFactory { @Override public <T extends Product> T create(Class<T> cls) { Product product=null; try{ product= (Product) Class.forName(cls.getName()).newInstance(); }catch (Exception ex){ ex.printStackTrace(); } return (T) product; } }
public static void main(String[] args) { //創建具體工廠類
ConcreteFactory factory = new ConcreteFactory(); //調用工廠方法獲取產品類1的實例
Product1 product1 = factory.create(Product1.class); System.out.println(product1); }
- 以上是簡單的一個通用框架,讀者可以根據自己的業務在其上拓展。
工廠方法模式的優點
- 良好的封裝性,代碼結構清晰,調用者不用關系具體的實現過程,只需要提供對應的產品類名稱即可。
- 易擴展性,在增加產品類的情況下,只需要適當的修改工廠類邏輯或者重新拓展一個工廠類即可。
- 屏蔽了產品類,產品類的變化調用者不用關心。比如在使用
JDBC
連接數據庫時,只需要改動一個驅動的名稱,數據庫就會從Mysql
切換到Oracle
,極其靈活。
工廠方法模式的升級
- 在復雜的系統中,一個產品的初始化過程是及其復雜的,僅僅一個具體工廠實現可能有些吃力,此時最好的做法就是為每個產品實現一個工廠,達到一個工廠類只負責生產一個產品。
- 此時工廠方法模式的類圖如下:

- 如上圖,每個產品類都對應了一個工廠,一個工廠只負責生產一個產品,非常符合單一職責原則。
- 針對上述的升級過程,那么工廠方法中不需要傳入抽象產品類了,因為一個工廠只負責一個產品的生產,此時的抽象工廠類如下:
public abstract class AbstractFactory { /** * 工廠方法,需要子類實現 */
public abstract <T extends Product> T create(); }
Spring底層如何使用工廠方法模式?
- 工廠方法模式在Spring底層被廣泛的使用,陳某今天舉個最常用的例子就是
AbstractFactoryBean
。
- 這個抽象工廠很熟悉了,這里不再討論具體的作用。其實現了
FactoryBean
接口,這個接口中getObject()
方法返回真正的Bean實例。
AbstractFactoryBean
中的getObject()
方法如下:
public final T getObject() throws Exception { //單例,從緩存中取,或者暴露一個早期實例解決循環引用
if (isSingleton()) { return (this.initialized ? this.singletonInstance : getEarlySingletonInstance()); } //多實例
else { //調用createInstance
return createInstance(); } } //創建對象
protected abstract T createInstance() throws Exception;
- 從以上代碼可以看出,創建對象的職責交給了
createInstance
這個抽象方法,由其子類去定制自己的創建邏輯。
- 下圖顯示了繼承了
AbstractFactoryBean
的具體工廠類,如下:

- 其實與其說
AbstractFactoryBean
是抽象工廠類,不如說FactoryBean
是真正的抽象工廠類,前者只是對后者的一種增強,完成大部分的可復用的邏輯。比如常用的sqlSessionFactoryBean
只是簡單的實現了FactoryBean
,並未繼承AbstractFactoryBean
,至於結論如何,具體看你從哪方面看了。
總結
- 工廠方法模式是一種常見的設計模式,但是真正能夠用的高級,用的透徹還是有些難度的,開發者所能做的就是在此模式基礎上思考如何優化自己的代碼,達到易擴展、封裝性強的效果了。