簡單工廠(靜态工廠)
定義:由一個工廠對象決定建立出哪一種産品類的執行個體
類型:建立型,不屬于GOF23種設計模式
适用場景:
- 工廠類負責建立的對象比較少
- 用戶端(應用層)隻知道傳入工廠類的參數,對于如何建立對象(邏輯)并不關心
優點:
- 隻需要傳入一個正确的參數,就可以擷取你所需要的對象而不需要知道其建立的細節
缺點:
- 工廠類的職責相對過重,增加新的産品需要修改工廠類的判斷邏輯,違背了開閉原則
UML類圖:
IProduct:抽象産品接口,具體産品都需要遵循的規範
Product:具體産品實作類
Creator:工廠類,提供工廠方法建立産品執行個體
示例
我們知道不同品牌的列印機都需要安裝相應品牌的驅動程式才能正常使用,這裡以惠普和佳能列印機為例
- 直接在使用時候由用戶端建立産品對象
//使用佳能列印機,需要在用戶端主動new對象
CanonPrinter canonPrinter = new CanonPrinter();
canonPrinter.print();
//使用惠普列印機
HpPrinter hpPrinter = new HpPrinter();
hpPrinter.print();
- 使用簡單工廠模式,産品對象的建立全部交給工廠對象(或工廠類),隻需要傳遞關于産品的參數即可
/**
* 各個列印機需要實作的列印機接口(産品接口)
*/
public interface IPrinter {
void print();
}
/**
* 佳能列印機(具體産品)
*/
public class CanonPrinter implements IPrinter {
@Override
public void print(){
System.out.println("佳能列印機開始列印...");
}
}
/**
* 惠普列印機(具體産品)
*/
public class HpPrinter implements IPrinter{
@Override
public void print(){
System.out.println("惠普列印機開始列印...");
}
}
/**
* 列印機工廠(負責根據參數建立産品執行個體)
*/
public class PrinterFactory {
/**
* 如果該工廠仍然需要提供給子類擴充,則去掉工廠的靜态方法,修改為執行個體方法,去掉私有構造,這裡是當 成是靜态工廠使用
*/
private PrinterFactory(){
}
public static IPrinter createPrinter(String printerName){
if("canon".equals(printerName)){
return new CanonPrinter();
}else if("hp".equals(printerName)){
return new HpPrinter();
}
return null;
}
}
public static void main(String[] args) {
IPrinter canonPriner = PrinterFactory.createPrinter("canon");
canonPriner.print();
IPrinter hpPrinter = PrinterFactory.createPrinter("hp");
hpPrinter.print();
}
- 在簡單工廠的基礎上加上反射技術,修改PrinterFactory中的createPrinter方法和參數,讓輸入參數可控
public static IPrinter createPrinter(Class<? extends IPrinter> clazz) throws IllegalAccessException, InstantiationException {
return clazz.newInstance();
}
上面中的的列印機執行個體都是由一個列印機工廠類進行建立,如果增加了不同的列印機,則仍然需要修改該工廠類,違反了開閉原則。在後面的工廠方法模式就可以解決這個問題,工廠方法模式中,就是将産品對象的建立延遲到工廠子類去實作,每當需要生産一種産品,就需要引入一個新的工廠類,這樣對于用戶端說來,建立不同産品,隻需要更改其抽象産品工廠的實作類即可,對開閉原則友好
使用典範
- java.util.Calendar
/**
* Gets a calendar using the default time zone and specified locale.
* The <code>Calendar</code> returned is based on the current time
* in the default time zone with the given locale.
*
* @param aLocale the locale for the week data
* @return a Calendar.
*/
public static Calendar getInstance(Locale aLocale)
{
return createCalendar(TimeZone.getDefault(), aLocale);
}