前言
簡單工廠模式,雖然不在23種設計模式中。但是可以認為是工廠模式的一種特殊實現,並且在日常中使用廣泛,所以還是值得我們去學習的。
定義
-
簡單工廠模式(Simple Factory Pattern):又稱為靜態工廠方法(Static Factory Method)模式,是一種創建型的設計模式,關注於實例對象創建。
- 由一個工廠對象通過判斷傳入的參數,決定創建出哪一種產品類的實例,將創建的細節透明化。
注意:簡單工廠不屬於GOF23種之一。
場景
在週一陽光明媚的上午,剛帶上耳機,準備開始一天的工作,老闆突然來到你身旁。
- 老闆: xxx啊,聽說你是學計算機的?
- 我:是的,學的是軟件工程。
- 老闆:那幫我組裝一臺蘋果電腦出來吧,週五送到我辦公桌上。
- 我:內心OS:修電腦,我也就認了,這竟然讓我組裝一臺蘋果電腦,你咋不上天呢?
- 老闆:預算5000,記得不要超支了。
- 我:內心雖然波濤洶湧,但是還是說了聲,好的老闆。
於是我就立馬打開chrome,上各大論壇搜索完美黑蘋果配置,在初步確定好配置後,就開始上京東,開始選購CPU,主板,固態,內存,電源等配件。在經歷了兩天的等待,所有配件終於到齊以後,耗費九牛二虎之力,終於在週五前把電腦給組裝好了。
可是呢沒過多久,總經理也找我說讓我幫他組一臺蘋果電腦,和老闆同樣的套路,我能咋辦,我也很無耐,但是給的預算更低只有4000於是我也只能在原來的基礎上縮減一下配置,勉強達到了要求。
我在想要是每個領導都這樣,那我不是得涼涼啊,想到這裡我暗自下定決心,對自己說我下次一定要拒絕他們。
優點
只需要知道產品的名稱即可,就可以創建你所需要的對象,而無需知道其創建細節。
缺點
工廠類的職責相對過重,增加新的產品需要修改工廠類的判斷邏輯,違背開閉原則,如果產品數量過多,維護將變得非常困難。
注意:使用反射和枚舉可以避免頻繁修改工廠類。
使用場景
- 將實例化過程非常複雜的類,通過工廠進行簡化,方便業務方使用。
- 把創建對象的職責集中管理和控制。
小結
從上面的小故事可以簡單的理解為:老闆就是需求方,我就是工廠,老闆只需要告訴我,他需要什麼就好了,不管我如何實現。但是如果需要的產品變更了,我就只能做修改來滿足要求。
UML模型
代碼實例
BaseComputer
public abstract class BaseComputer {
/**
* 開機
*/
protected abstract void turnOn();
}
MacBookPro
public class MacBookPro extends BaseComputer {
@Override
protected void turnOn() {
System.out.println("MacBook Pro 開機了");
}
}
ThinkPad
public class ThinkPad extends BaseComputer {
@Override
protected void turnOn() {
System.out.println("Think Pad 開機了");
}
}
ComputerFactory
public class ComputerFactory {
/**
* 創建電腦
* @param name 名稱
* @return 返回電腦
*/
public static BaseComputer create(String name){
if("mac".equals(name)){
return new MacBookPro();
}else if("thinkPad".equals(name)){
return new ThinkPad();
}else {
throw new IllegalArgumentException("無法創建"+name+"電腦。");
}
}
}
測試
public class Test {
public static void main(String[] args) {
BaseComputer mac = ComputerFactory.create("mac");
mac.turnOn();
BaseComputer thinkPad = ComputerFactory.create("thinkPad");
thinkPad.turnOn();
BaseComputer dell = ComputerFactory.create("dell");
dell.turnOn();
}
}
測試結果
MacBook Pro 開機了
Think Pad 開機了
Exception in thread "main" java.lang.IllegalArgumentException: 無法創建dell電腦。
at simple.factory.ComputerFactory.create(ComputerFactory.java:22)
at simple.factory.Test.main(Test.java:18)
重構ComputerFactory - Switch
對於ComputerFactory使用if的寫法不是很優雅,對此我們可以改成使用switch語句。
注意:Java7以後的版本switch才支持字符串,Java7以前只支持int 、short 、byte 、char
public class ComputerFactory {
/**
* 創建電腦
* @param name 名稱
* @return 返回電腦
*/
public static BaseComputer create(String name){
switch (name){
case "mac":
return new MacBookPro();
case "thinkPad":
return new ThinkPad();
default:
throw new IllegalArgumentException("無法創建"+name+"電腦。");
}
}
}
重構ComputerFactory - 反射
public class ComputerFactory {
/**
* 創建電腦
* @param name 名稱
* @return 返回電腦
*/
public static BaseComputer create(String name) {
BaseComputer computer;
try {
computer = (BaseComputer) Class.forName(name).getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e ) {
throw new IllegalArgumentException("無法創建"+name+"電腦。");
}
return computer;
}
}
測試類
public class Test {
public static void main(String[] args) {
BaseComputer mac = ComputerFactory.create("simple.factory.MacBookPro");
mac.turnOn();
BaseComputer thinkPad = ComputerFactory.create("simple.factory.ThinkPad");
thinkPad.turnOn();
BaseComputer dell = ComputerFactory.create("simple.factory.Dell");
dell.turnOn();
}
}
重構ComputerFactory - 反射 + 枚舉
public class ComputerFactory {
/**
* 創建電腦
* @param name 名稱
* @return 返回電腦
*/
public static BaseComputer create(ComputerEnum name) {
BaseComputer computer;
try {
computer = (BaseComputer) name.getClazz().newInstance();
} catch (InstantiationException | IllegalAccessException e ) {
throw new IllegalArgumentException("無法創建"+name+"電腦。");
}
return computer;
}
}
電腦枚舉類
public enum ComputerEnum {
/**
* 電腦枚舉類
*/
MAC_BOOK_PRO(MacBookPro.class),
THINK_PAD(ThinkPad.class),
;
private Class clazz;
ComputerEnum(Class clazz) {
this.clazz = clazz;
}
public Class getClazz() {
return clazz;
}
}
測試類
public class Test {
public static void main(String[] args) {
BaseComputer mac = ComputerFactory.create(ComputerEnum.MAC_BOOK_PRO);
mac.turnOn();
BaseComputer thinkPad = ComputerFactory.create(ComputerEnum.THINK_PAD);
thinkPad.turnOn();
}
}
結尾
如果覺得對你有幫助,可以多多評論,多多點贊哦,也可以到我的主頁看看,說不定有你喜歡的文章,也可以隨手點個關注哦,謝謝。
我是不一樣的科技宅,每天進步一點點,體驗不一樣的生活。我們下期見!