工廠方法模式
工廠方法模式是簡單工廠模式的延伸,它繼承了簡單工廠模式的優點,同時彌補了簡單工廠的缺陷,更好地符合開閉原則的要求,增加新的具體產品對象不需要對已有系統作任何修改。
模式定義
工廠方法模式又稱爲工廠模式,也叫虛擬構造器模式或者多態工廠模式,屬於類創建模式。在工廠模式中,工廠父類負責定義產品對象的公共接口,而子工廠模式負責生成具體的產品對象,這樣做的目的是將產品類實例化操作延遲到工廠子類中完成,即通過工廠子類來確定實例化哪一個對象。
模式結構
-
Product(抽象產品)
抽象產品是定義產品的接口,是工廠方法模式所創建對象的超類型,也就是產品對象的共同父類接口
-
ConcreteProduct(具體產品)
具體產品實現抽象產品接口,某種類型的具體產品由專門具體創建
-
Facory(抽象工廠)
在抽象工廠類中,聲明工廠方法,用於返回一個產品。抽象工廠是工廠方法模式的核心,任何在模式中創建對象的工廠類都必須實現該接口。
-
ConcreteFactory(具體工廠)
具體工廠是抽象工廠類的子類,實現了抽象工廠定義的工廠方法,返回一個具體產品類的實例。
模式分析
在工廠方法模式中,核心的工廠類不再負責所有產品的創建,而是將具體創建的工作交給了子類。核心類僅僅給出具體工廠實現的接口,而不負責哪一個產品被實例化的細節,使得工廠方法模式允許系統在不修改工廠角色的情況下引進新產品。
實際的開發應用中,不直接使用new關鍵字來創建對象,而是將具體類的類名寫入配置文件,在通過java反射機制,讀取XML格式的配置文件,根據存儲在XML文件的類名字符串生成對象。
工廠方法模式實例之手機工廠
-
實例說明
之前的簡單工廠模式時我們也創建過一個類似實例,但卻是違反了開閉原則的。通過工廠方法模式進行一次重構,將原有工廠進行分割,爲每種品牌的手機提供一個子工廠,使整個系統具有更好的靈活性和可擴展性。
-
實例類圖
-
實例代碼及解釋
-
抽象產品類Phone
public abstract class Phone { public abstract void use(); }
-
具體產品類HuaweiPhone
public class HuaweiPhone extends Phone { @Override public void use() { System.out.println("華爲手機使用中...."); } }
-
具體產品類XiaomiPhone
public class XiaomiPhone extends Phone { @Override public void use() { System.out.println("小米手機使用中...."); } }
-
抽象工廠類PhoneFactory
public interface PhoneFactory { Phone producePhone(); }
-
具體工廠類HuaweiPFactory
public class HuaweiPFactory implements PhoneFactory { @Override public Phone producePhone() { System.out.println("華爲工廠生產華爲手機......"); return new HuaweiPhone(); } }
-
具體工廠類XiaomiPFactory
public class XiaomiPFactory implements PhoneFactory { @Override public Phone producePhone() { System.out.println("小米工廠生產小米手機......"); return new XiaomiPhone(); } }
-
XML操作工具類
public class XMLUtilPhone { public static Object getBean() throws Exception { //創建解析器工廠 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); //創建解析器 DocumentBuilder builder = builderFactory.newDocumentBuilder(); //得到document Document document = builder.parse("configPhone.xml"); //獲取包含品牌名稱的文本節點 NodeList brandNameList = document.getElementsByTagName("factoryName"); Node classNode = brandNameList.item(0).getFirstChild(); String factoryName = classNode.getNodeValue().trim(); // System.out.println(factoryName); Class c = Class.forName("com.factoryMethod." + factoryName); Object o = c.newInstance(); return o; } }
-
配置文件
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <factoryName>XiaomiPFactory</factoryName> </configuration>
-
測試類
public class Test { public static void main(String[] args) throws Exception { PhoneFactory phoneFactory = (PhoneFactory) XMLUtilPhone.getBean(); Phone phone = phoneFactory.producePhone(); phone.use(); } }
-
結果分析
如果在配置文件將節點中內容設置爲 XiaomiPFactory,則輸出結果如下:
如果在配置文件將節點中內容設置爲 XiaomiPFactory,則輸出結果如下:
如果需要增加新的類型的手機,則首先要增加一個新的具體產品類,再增加對於的具體工廠類。
-