工廠方法模式
工廠方法模式又被稱爲虛擬構造器(Virtual Constructor)
作用
定義用於創建對象的接口,但是讓子類決定要實例化哪個類。工廠方法將類實例化推遲到子類。
說明
真實案例
- 鐵匠製造武器。精靈需要精靈武器和獸人需要獸醫武器。根據手頭的客戶,正確的類型的鐵匠被召喚。
- 發送器發送信息。短信發送器發送短信息和郵件發送器發送郵件信息。根據業務需求,調用正確類型的發送器發送信息。
簡而言之
工廠方法模式提供了一種將實例化邏輯委託給子類的方法
維基百科定義
在基於類的編程中,工廠方法模式是使用工廠方法來處理創建對象的問題的創建模式,而不必指定將要創建的對象的確切類。這可以通過調用工廠方法(在接口中指定並由子類實現)來實現,或者在基類中實現,並且可選地被派生類覆蓋,而不是調用構造函數。
程序示例
以我們的信息發送器爲例。首先我們有一個信息發送器接口和一些實現
/**
* 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 ();
}
}
這種工廠方法模式 擴展需要修改工廠類,等我們學習了抽象工廠模式再進一步改進。