抽象工廠模式是常見的建造型設計模式之一,比工廠方法模式抽象程度更高。工廠方法模式中具體工廠只生產一種具體產品,但在抽象工廠模式中,具體工廠能夠生產相關的一組具體產品,這樣一組產品稱爲產品族,產品族中的每個產品分屬於某一產品繼承等級結構。java
有時候咱們須要一個工廠提供多個產品對象,而不是單一一個產品對象,如一個電器設備工廠,它能夠生產電視機、電冰箱、空調等設備,而不僅是生成某種類型的電器。爲了更清晰地理解抽象工廠模式,這裏先引入兩個概念:設計模式
產品等級結構:產品等級結構即產品的繼承結構,如一個抽象類是電視機,其子類有海爾電視機、TCL電視機等,抽象電視機與具體品牌電視機之間構成了一個產品等級結構。ide
產品族:指由同一工廠生產的,位於不一樣產品等級結構中的一組產品,如海爾電器工廠生產海爾電視機、海爾電冰箱,則它們是同一產品族,各自位於不一樣產品等級結構。工具
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KyRte5v6-1583586756775)(C:\Users\LENOVO\AppData\Roaming\Typora\typora-user-images\image-20200307152957643.png)]測試
當系統提供的工廠生產的具體產品不是一個簡單對象,而是多個位於不一樣產品等級結構中屬於不一樣類型的具體產品時須要使用抽象工廠模式。ui
提供一個建立一系列相關或相互依賴對象的接口,而無須指定它們具體的類。設計
AbstractFacory(抽象工廠)3d
抽象工廠用於聲明生產抽象產品的方法,在一個抽象工廠中能夠定義一組方法,每一方法對應一個產品等級結構code
ConcreteFactory(具體工廠)xml
具體工廠實現抽象工廠聲明的生產抽象產品的方法,生產一組具體產品,這些產品構成一個產品族,每個產品都位於某個產品等級結構中。
AbstractProduct(抽象產品)
抽象產品爲每種產品聲明接口,在抽象產品中定義產品的抽象業務方法
ConcreteProduct(具體產品)
具體產品定義具體工廠生產的具體產品對象,實現抽象產品接口中定義的業務方法。
一個電器工廠能夠產生多種類型的電器,如海爾工廠能夠生產海爾電視機、海爾空調等,TCL工廠能夠生產TCL電視機、TCL空調等,相同品牌的電器構成一個產品族,而相同類型電器構成一個產品等級結構。
抽象產品類Television
public interface Television { void play(); }
具體產品類HairTelevision(海爾電視機類)
public class HairTelevision implements Television { @Override public void play() { System.out.println("海爾電視機播放中......"); } }
具體產品類TCLTelevision(TCL電視機類)
public class TCLTelevision implements Television { @Override public void play() { System.out.println("TCL電視機播放中......."); } }
抽象產品類AirConditioner
public interface AirConditioner { void changeTemperature(); }
具體產品類HairAirConditioner(海爾空調類)
public class HairAirConditioner implements AirConditioner { @Override public void changeTemperature() { System.out.println("海爾空調溫度改變中....."); } }
具體產品類TCLAirConditioner(TCL空調類)
public class TCLAirConditioner implements AirConditioner { @Override public void changeTemperature() { System.out.println("TCL空調溫度改變中......"); } }
抽象工廠類EFactory
public interface EFactory { Television produceTelevision(); AirConditioner produceAirConditioner(); }
具體工廠類HairFactory(海爾工廠類)
public class HairFactory implements EFactory { @Override public Television produceTelevision() { return new HairTelevision(); } @Override public AirConditioner produceAirConditioner() { return new HairAirConditioner(); } }
具體工廠類TCLPFactory
public class TCLFactory implements EFactory { @Override public Television produceTelevision() { return new TCLTelevision(); } @Override public AirConditioner produceAirConditioner() { return new TCLAirConditioner(); } }
XML操做工具類
public class XMLUtil { 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.abstractFactory." + factoryName); Object o = c.newInstance(); return o; } }
配置文件
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <factoryName>HairFactory</factoryName> </configuration>
測試類
public class Test { public static void main(String[] args) throws Exception { EFactory factory = (EFactory) XMLUtil.getBean(); Television television = factory.produceTelevision(); television.play(); AirConditioner airConditioner = factory.produceAirConditioner(); airConditioner.changeTemperature(); } }
結果分析
若是在配置文件將節點中內容設置爲 HairFactory,則輸出結果以下:
若是在配置文件將節點中內容設置爲 TCLFactory,則輸出結果以下:
若是須要增長新品牌的電器,即增長一個新的產品族,如增長海信電視機和海信空調,則只需對應增長一個具體工廠,再將配置文件中具體工廠類名修改成新增工廠類名,原有代碼無須修改。但若是要增長新的產品,如增長新的電器產品洗衣機,抽象工廠須要聲明一個生產洗衣機的方法,全部具體工廠類都需實現該方法,將致使系統再也不符合開閉原則。