精通設計模式之工廠方法模式

工廠方法模式

工廠方法模式又被稱爲虛擬構造器(Virtual Constructor)

作用

定義用於創建對象的接口,但是讓子類決定要實例化哪個類。工廠方法將類實例化推遲到子類。

說明

真實案例

  1. 鐵匠製造武器。精靈需要精靈武器和獸人需要獸醫武器。根據手頭的客戶,正確的類型的鐵匠被召喚。
  2. 發送器發送信息。短信發送器發送短信息和郵件發送器發送郵件信息。根據業務需求,調用正確類型的發送器發送信息。

簡而言之

工廠方法模式提供了一種將實例化邏輯委託給子類的方法

維基百科定義

在基於類的編程中,工廠方法模式是使用工廠方法來處理創建對象的問題的創建模式,而不必指定將要創建的對象的確切類。這可以通過調用工廠方法(在接口中指定並由子類實現)來實現,或者在基類中實現,並且可選地被派生類覆蓋,而不是調用構造函數。

程序示例

以我們的信息發送器爲例。首先我們有一個信息發送器接口和一些實現

/**
 * Description: 定義發送者接口
 * <br /> Author: vimx86
 */
public interface Sender {

    /**
     * 發送信息
     */
    void send();

}

/**
 * Description: 郵件發送者
 * <br /> Author: vimx86
 */
public class MailSender implements Sender {
    @Override
    public void send() {
        System.out.println("郵件發送者發送了一封郵件!");
    }
}

/**
 * Description: 短信息發送者
 * <br /> Author: vimx86
 */
public class SmsSender implements Sender {
    @Override
    public void send() {
        System.out.println("短信息發送者發送了一封郵件!");
    }
}

定義信息發送器生產工廠

/**
 * Description: 發送工廠(普通工廠模式)
 * <br /> Author: vimx86
 */
public class SimpleSendFactory {

    /**
     * 根據發送者類型名稱生產對應發送者
     *
     * @param type 發送者類型
     * @return 具體發送者
     */
    public Sender produce(String type) {
        if ("mail".equals(type)) {
            return new MailSender();
        } else if ("sms".equals(type)) {
            return new SmsSender();
        } else {
            System.out.println("請輸入正確的類型!");
            return null;
        }
    }

}

現在,根據發送器類型調用正確的信息發送器併發送信息。

/**
 * Description: 測試普通工廠模式
 * <br /> Author: vimx86
 */
public class SimpleSendFactoryTest {
    @Test
    public void test() throws Exception {
        SimpleSendFactory factory = new SimpleSendFactory();
        Sender sender = factory.produce("sms");
        sender.send();
    }
}

適用場景

何時使用“工廠方法”模式

  • 一個類不能預期它必須創建的對象類
  • 一個類希望其子類來指定它創建的對象
  • 類將責任委託給幾個輔助子類之一,並且您想要本地化哪個助手子類是委託的知識

Known uses

點進去看一看,理解一下 ^_^!!!
* java.util.Calendar
* java.util.ResourceBundle
* java.text.NumberFormat
* java.nio.charset.Charset
* java.net.URLStreamHandlerFactory
* java.util.EnumSet
* javax.xml.bind.JAXBContext

信息發送案例

  • 普通工廠模式
  • 多個工廠方法模式
  • 靜態工廠方法模式

工廠模式適合:凡是出現了大量的產品需要創建,並且具有共同的接口時,可以通過工廠方法模式進行創建。
在以上的三種模式中,第一種如果傳入的字符串有誤,不能正確創建對象,
第三種相對於第二種,不需要實例化工廠類,
所以,大多數情況下,我們會選用第三種——靜態工廠方法模式。

工廠方法模式的運用

結合實際業務進行分析運用設計案例

業務場景

獲取不同票務商(大衆,貓眼,蜘蛛等等)提供的影院實時座位圖。
考慮業務擴展,保證有新票務商的接入時不影響當前業務。提供擴展性,可維護性。

分析設計

因爲每家票務商都需要提供實時座位圖功能,故可抽象出共同的接口 實時座位圖提供商 提供實時座位圖功能。

定義實時座位圖提供商接口 RealTimeSeats 和實現具體票務商的子類。

public interface RealTimeSeats{
    /**
    * 獲取實時座位圖信息
    */
    RealtimeSeatModel getSeats(RealTimeSeatsRequest realTimeSeatsRequest);
}

/**
 * Description: 貓眼獲取實時座位圖
 * <br /> Author: vimx86
 */
public class MaoYanRealTimeSeats implements RealTimeSeats{
    @Override
    public RealtimeSeatModel getSeats(RealTimeSeatsRequest realTimeSeatsRequest) {
          // 貓眼獲取實時座位圖邏輯調用……
   }
}

/**
 * Description: 蜘蛛網獲取實時座位圖
 * <br /> Author: vimx86
 */
public class SpiderRealTimeSeats implements RealTimeSeats{
    @Override
    public RealtimeSeatModel getSeats(RealTimeSeatsRequest realTimeSeatsRequest) {
        // 蜘蛛網獲取實時座位圖邏輯調用……
    }
}

定義獲取實時座位圖工廠


/**
 * Description: 實時座位圖工廠
 * <br /> Author: vimx86
 */
public class RealTimeSeatsFactory {

    public static RealTimeSeats produceSpider() {
        return new SpiderRealTimeSeats ();
    }

    public static RealTimeSeats produceMaoYan() {
        return new MaoYanRealTimeSeats ();
    }

}

這種工廠方法模式 擴展需要修改工廠類,等我們學習了抽象工廠模式再進一步改進。

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章