Java 設計模式實戰系列—工廠模式

2023-06-30 09:00:34

在 Java 開發中,物件的建立是一個常見的場景,如果物件的建立和使用都寫在一起,程式碼的耦合度高,也不利於後期的維護。我們可以使用工廠模式來解決這個問題,工廠模式是一個建立型模式,將物件的建立和使用分離開來,降低程式碼的耦合度,提高程式的可維護性和擴充套件性。

工廠模式應用場景

  • 呼叫方無需關注物件的建立過程,只需要直接呼叫即可。
  • 具體子類的數目不確定,後續可能會新增或者減少子類的數量。對子類的使用不確定
  • 呼叫方根據引數來呼叫對應的物件。

從多種支付種類說起

電商平臺下單之後,支付需要可以選擇不同的支付的方式,比如拼多多下單後,就會有以下的支付方式:

工廠模式定義:定義一個建立物件的介面,讓其子類自己決定範例化哪一個工廠類,工廠模式使其建立過程延遲到子類進行

建立支付介面以及實現類

首先定義一個支付介面,以及幾個實現類,比如微信支付,支付寶支付:

// 支付介面
public interface Pay {
    void pay();
}

// 支付寶支付
public class AliPay implements Pay{
    @Override
    public void pay() {
        System.out.println("支付寶支付 .....");
    }
}

// 微信支付
public class WechatPay implements Pay{

    @Override
    public void pay() {
        System.out.println("微信支付 .....");
    }
}

沒使用工廠模式之前,一個下單方法裡面包含建立訂單、支付、更新訂單方法,所以程式碼都冗餘到了一起:

public void order(int payType) {
    // 建立訂單
    // 省略程式碼......
    // 根據type 呼叫不同的支付
    Pay pay;
    if (payType == 1) {
        pay = new AliPay();
    } else {
        pay = new WechatPay();
    }
    // 呼叫支付
    pay.pay();
    // 更新狀態 程式碼省略.....
}

以上程式碼耦合度很高,有以下幾個缺點:

  • 違反單一職責原則,物件的建立散落在多個地方,沒有一個統一的地方處理物件建立,程式碼耦合度高。
  • 程式碼可讀性差,後續閱讀程式碼難度增加。
  • 難以擴充套件和修改,後續新增新的支付方法,或者更修支付方式,需要在多個地方修改程式碼,增加程式碼的維護成本。

引入工廠類

將 order 方法的支付程式碼抽取到工廠類中:

// 支付工廠類
public class PayFactory {

  public static Pay getPay(int payType) {
      Pay pay;
      if (payType == 1) {
          pay = new AliPay();
      } else {
          pay = new WechatPay();
      }
      return pay;
  }

}

經過重構之後的 order 方法,支付直接呼叫 PayFactory 工廠類,程式碼邏輯更加清晰,可讀性也更強了:

public void order2(int payType) {
    // 建立訂單
    // 省略程式碼......
    // 根據type 呼叫不同的支付
    Pay pay  = PayFactory.getPay(payType);
    // 呼叫支付
    pay.pay();
    // 更新狀態 程式碼省略.....

}

  • 引入工廠模式之後,程式碼有如下的優點:

    • 實現物件的建立和使用解耦,呼叫方無需關注物件的建立,直接呼叫即可。
    • 增加的程式碼的可延伸性和靈活性,新增或者修改物件,只需要在工廠類修改即可,降低程式碼的維護成本。
    • 程式碼可讀性大大增加。

需要注意的是,上面範例類只有一個方法,僅僅是因為方便,還可以寫其他方法,因為工廠模式重點是物件的建立,所以可以包含多個方法

工廠模式在 JDK 中的應用

工廠模式作為場景的一種設計模式,在 JDK 使用也比較廣泛,這裡就介紹幾種使用範例。

Calendar.getInstance

Calendar 類提供了大量跟日期相關的功能程式碼,Calendar 是一個抽象類,通過呼叫 Calendar.getInstance() 來獲取物件,最終會呼叫 createCalendar方法,來看一下原始碼:

從程式碼可以看出 getInstance 根據 TimeZone 和 Locale 的不同的,返回不同的 Calendar 子類物件,比如 BuddhistCalendar、JapaneseImperialCalendar。將物件的建立封裝成一個工廠方法,呼叫只需要傳遞當時時區和地址,就能獲取到對應的物件了,無需關心物件是如何建立的。

總結

  • 在 Java 開發中如果將物件的建立和使用耦合在一起,不利於後期的維護,這就需要引入工廠模式。
  • 工廠模式將物件的建立和使用分離,降低程式碼的耦合度。
  • 定義一個建立物件的介面,讓其子類自己決定範例化哪一個工廠類,工廠模式使其建立過程延遲到子類進行。
  • 引入工廠模式之後,呼叫方無需關注物件的建立過程,根據傳參呼叫對應的範例物件,後續新增或更新物件只需要修改工廠方法即可,降低程式碼的維護成本。

參考

感覺不錯的話,點點關注