工廠方法模式是簡單工廠模式的延伸,它繼承了簡單工廠模式的優點,同時彌補了簡單工廠的缺陷,更好地符合開閉原則的要求,增加新的具體產品物件不需要對已有系統作任何修改,
模式定義
工廠方法模式又稱為工廠模式,也叫虛擬構造器模式或者多型工廠模式,屬于類創建模式,在工廠模式中,工廠父類負責定義產品物件的公共介面,而子工廠模式負責生成具體的產品物件,這樣做的目的是將產品類實體化操作延遲到工廠子類中完成,即通過工廠子類來確定實體化哪一個物件,
模式結構

-
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,則輸出結果如下:

如果需要增加新的型別的手機,則首先要增加一個新的具體產品類,再增加對于的具體工廠類,
-
模式優缺點
工廠方法模式優點:
- 工廠方法為用戶創建客戶所需的產品,向客戶隱藏了具體產品類被實體化的細節
- 基于介面開發的工廠角色和產品角色實作了多型性設計
- 向系統加入新產品時,無須修改抽象工廠和抽象產品提供的介面,也無須修改其他具體工廠和產品,只要添加一個具體工廠和具體產品即可,完全符合開閉原則
工廠方法模式缺點:
- 添加新產品時,需要提供新的具體產品類和對應的具體工廠類,類的個數會成對增加,增加系統復雜性
- 更多的類需要編譯和運行,給系統帶來額外的開銷
模式適用環境
以下情況可以使用工廠方法模式:
- 一個類不知道它所需要的類的物件,客戶端不需要知道具體產品類的類名,只需知道所對應的工廠即可
- 一個類通過其子類來指定創建哪個物件,對于抽象工廠類只需提供一個創建產品的介面,由其子類來確定具體要創建的物件
模式應用
在 Java 集合框架中,常用的 List 和 Set 等集合都實作了 Collection 介面,Collection 介面為所有的 Java 集合類定義了一個 iterator() 方法,可回傳一個用于遍歷集合 Iterator(迭代器)型別的物件,而 Java 集合類可以實作該 iterator() 方法來回傳一個具體的迭代器物件,

實際的程序實作相對復雜,這里僅給出簡化版,List 介面除了繼承 Collection 介面的 iterator() 方法外,還增加了新的工廠方法 listIterator(),專門用于創建 ListIterator 型別的迭代器,在 List 的子類 LinkedList 在實作了該方法,可用于創建 ListIterator 子類 ListItr 的物件并回傳,是一個具體的工廠方法
public ListIterator<E> listIterator(int index) {
return new ListItr(index);
}
在 JDBC 中也大量使用了工廠方法模式,在創建連接物件 Connection、Statement、ResultSet 時都使用了工廠方法
Connection con = DriveManager.getConnection(".....");
Statement statement = con.createStatement();
ResultSet rs = statement.executeQuery(".....")
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/83418.html
標籤:其他
