工廠方法模式是簡單工廠模式的延伸,它繼承了簡單工廠模式的優勢,同時彌補了簡單工廠的缺陷,更好地符合開閉原則的要求,增長新的具體產品對象不須要對已有系統做任何修改。java
工廠方法模式又稱爲工廠模式,也叫虛擬構造器模式或者多態工廠模式,屬於類建立模式。在工廠模式中,工廠父類負責定義產品對象的公共接口,而子工廠模式負責生成具體的產品對象,這樣作的目的是將產品類實例化操做延遲到工廠子類中完成,即經過工廠子類來肯定實例化哪個對象。ide
Product(抽象產品)工具
抽象產品是定義產品的接口,是工廠方法模式所建立對象的超類型,也就是產品對象的共同父類接口測試
ConcreteProduct(具體產品)ui
具體產品實現抽象產品接口,某種類型的具體產品由專門具體建立code
Facory(抽象工廠)xml
在抽象工廠類中,聲明工廠方法,用於返回一個產品。抽象工廠是工廠方法模式的核心,任何在模式中建立對象的工廠類都必須實現該接口。對象
ConcreteFactory(具體工廠)blog
具體工廠是抽象工廠類的子類,實現了抽象工廠定義的工廠方法,返回一個具體產品類的實例。繼承
在工廠方法模式中,核心的工廠類再也不負責全部產品的建立,而是將具體建立的工做交給了子類。核心類僅僅給出具體工廠實現的接口,而不負責哪個產品被實例化的細節,使得工廠方法模式容許系統在不修改工廠角色的狀況下引進新產品。
實際的開發應用中,不直接使用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,則輸出結果以下:
若是須要增長新的類型的手機,則首先要增長一個新的具體產品類,再增長對於的具體工廠類。