Spring中的設計模式:工廠方法模式


導讀

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

什么是工廠方法模式?

  • 定義:定義一個用於創建對象的 接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。
  • 工廠方法模式通用類圖如下: 
  • 在工廠方法模式中,抽象產品Product負責定義產品的特性,實現對事物的抽象定義。
  • AbstractFactory是抽象工廠類,定義了一個抽象工廠方法。具體的如何創建產品由工廠實現類ConcreteFactory完成。

通用框架實現

  • 工廠方法模式的變種有很多,陳某給出一個比較實用的通用框架。
  • 抽象產品類
public abstract class Product { /** * 公共邏輯方法 */
    public void method1(){} /** * 抽象方法:由子類實現,根據業務邏輯定義多個 */
    public abstract void method2(); }
 
  • 具體產品類1,繼承抽象產品類,如下:
public class Product1 extends Product { /** * 實現抽象產品類的抽象方法 */ @Override public void method2() { } }
 
  • 具體產品類2,繼承抽象產品類,如下:
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,至於結論如何,具體看你從哪方面看了。

總結

  • 工廠方法模式是一種常見的設計模式,但是真正能夠用的高級,用的透徹還是有些難度的,開發者所能做的就是在此模式基礎上思考如何優化自己的代碼,達到易擴展、封裝性強的效果了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM