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,至於結論如何,具體看你從哪方面看了。

總結

  • 工廠方法模式是一種常見的設計模式,可是真正可以用的高級,用的透徹仍是有些難度的,開發者所能作的就是在此模式基礎上思考如何優化本身的代碼,達到易擴展、封裝性強的效果了。
相關文章
相關標籤/搜索