1.1 定義
簡單工廠模式屬於建立型模式,又稱為靜態工廠方法模式,在簡單工廠模式中,可以根據引數的不同,來返回不同類的例項,簡單工廠模式專門定義一個類來負責建立子類的例項,被建立的類通常有一個共同的父類
1.2 簡單工廠模式結構圖(簡版)
Factory:工廠類,簡單工廠模式的核心,它負責實現建立所有例項的內部邏輯。工廠類的建立產品類的方法可以被外界直接呼叫,建立所需的產品物件
IProduct:抽象產品類,簡單工廠模式所建立的所有物件的父類,它負責描述所有例項所共有的公共介面
Product:具體產品類,是簡單工廠模式的目標類
1.3 簡單工廠的實現一
假設有一個電腦的代工生產商,它目前已經可以代工生產聯想電腦了,隨著業務的擴充,這個代工生產商還要生產惠普和mac電腦;
這樣我們就需要用一個單獨的類來專門生產電腦,這就用到了簡單工廠模式,同時用到了繼承、封裝、多型等物件導向程式設計的思想,下面我們來實現簡單工廠模式
1.3.1 產品抽象類
public abstract class Computer { /** * 產品的抽象方法,由具體的產品類去實現 */ public abstract void start(); }
1.3.2 具體實現類
public class LenovoComputer extends Computer { @Override public void start() { System.out.println("lenovo computer run"); } }
public class MacComputer extends Computer { @Override public void start() { System.out.println("Mac computer run"); } }
public class HpComputer extends Computer { @Override public void start() { System.out.println("hp computer run"); } }
1.3.3 工廠類
public class ComputerFactory { public static Computer createComputer(String type) { Computer computer = null; switch (type) { case "lenovo": computer = new LenovoComputer(); break; case "hp": computer = new HpComputer(); break; case "Mac": computer = new MacComputer(); break; default: break; } return computer; } }
1.3.4 UML類圖
1.4 優缺點
優點:
1. 工廠類含有必要的判斷邏輯,可以決定在什麼時候建立哪一個產品類的例項,客戶端可以免除直接建立產品物件的責任,而僅僅“消費”產品;實現了對責任的分割,它提供了專門的工廠類用於建立物件。
2. 客戶端無須知道所建立的具體產品類的類名,只需要知道具體產品類所對應的引數即可,對於一些複雜的類名,通過簡單工廠模式可以減少使用者的記憶量。
3. 通過引入配置檔案,可以在不修改任何客戶端程式碼的情況下更換和增加新的具體產品類,在一定程度上提高了系統的靈活性。
缺點:
1. 由於工廠類集中了所有產品建立邏輯,一旦不能正常工作,整個系統都要受到影響。
2. 使用簡單工廠模式將會增加系統中類的個數,在一定程式上增加了系統的複雜度和理解難度。
3. 系統擴充套件困難,一旦新增新產品就不得不修改工廠邏輯,同樣破壞了“開閉原則”;在產品型別較多時,有可能造成工廠邏輯過於複雜,不利於系統的擴充套件和維護。
4. 簡單工廠模式由於使用了靜態工廠方法,造成工廠角色無法形成基於繼承的等級結構
1.5 適用場景
1. 工廠類負責建立的物件比較少:由於建立的物件較少,不會造成工廠方法中的業務邏輯太過複雜。
2. 客戶端只知道傳入工廠類的引數,對於如何建立物件不關心:客戶端既不需要關心建立細節,甚至連類名都不需要記住,只需要知道型別所對應的引數。
1.6 模式應用
1. JDK類庫中廣泛使用了簡單工廠模式,如工具類java.text.DateFormat,它用於格式化一個本地日期或者時間
public final static DateFormat getDateInstance(); public final static DateFormat getDateInstance(int style); public final static DateFormat getDateInstance(int style,Locale locale);2. 獲取不同加密演算法的金鑰生成器
KeyGenerator keyGen=KeyGenerator.getInstance("DESede");
1.7 開閉原則
對於上面兩種簡單工廠模式的實現方法,如果我們要新增新的 parser,那勢必要改動到 RuleConfigParserFactory 的程式碼,那這是不是違反開閉原則呢?
實際上,如果不是需要頻繁地新增新的 parser,只是偶爾修改一下 RuleConfigParserFactory 程式碼,稍微不符合開閉原則,也是完全可以接受的。
儘管簡單工廠模式的程式碼實現中,有多處 if 分支判斷邏輯,違背開閉原則,但權衡擴充套件性和可讀性,這樣的程式碼實現在大多數情況下(比如,不需要頻繁地新增 parser,也沒有太多的 parser)是沒有問題的