抽象工廠模式
模式動機與定義
模式動機
- 產品等級結構:產品等級結構即產品的繼承結構,例如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構成了一個產品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。
- 產品族:在抽象工廠模式中,產品族是指由同一個工廠生產的,位於不同產品等級結構中的一組產品,例如海爾電器工廠生產的海爾電視機、海爾電冰箱,海爾電視機位於電視機產品等級結構中,海爾電冰箱位於電冰箱產品等級結構中。

模式定義
- 抽象工廠模式(Abstract Factory Pattern):提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。抽象工廠模式又稱為Kit模式,屬於對象創建型模式。

模式結構與分析
模式結構

抽象工廠模式包含如下角色:
- AbstractFactory:抽象工廠
- ConcreteFactory:具體工廠
- AbstractProduct:抽象產品
- ConcreteProduct:具體產品
模式分析



模式實例與解析
模式實例
電器工廠:實例說明
- 一個電器工廠可以生產多種類型的電器,如海爾工廠可以生產海爾電視機、海爾空調等,TCL工廠可以生產TCL電視機、TCL空調等,相同品牌的電器構成一個產品族,而相同類型的電器構成了一個產品等級結構,現使用抽象工廠模式模擬該場景。
電器工廠:參考類圖

電器工廠:參考代碼
代碼結構

Television接口
package abstractfactory; public interface Television { public void play(); }
HaierTelevision類
package abstractfactory; public class HaierTelevision implements Television { @Override public void play() { System.out.println("海爾電視機播放中···"); } }
TCLTelevision類
package abstractfactory; public class TCLTelevision implements Television { @Override public void play() { System.out.println("TCL電視機播放中···"); } }
AirConditioner接口
package abstractfactory; public interface AirConditioner { public void changeTemperature(); }
HaierAirConditioner類
package abstractfactory; public class HaierAirConditioner implements AirConditioner { @Override public void changeTemperature() { System.out.println("海爾空調溫度改變中···"); } }
TCLAirConditioner類
package abstractfactory; public class TCLAirConditioner implements AirConditioner { @Override public void changeTemperature() { System.out.println("TCL空調溫度改變中···"); } }
EFactory接口
package abstractfactory; public interface EFactory { public Television produceTelevision(); public AirConditioner produceAirConditioner(); }
HaierFactory類
package abstractfactory; public class HaierFactory implements EFactory { @Override public Television produceTelevision() { return new HaierTelevision(); } @Override public AirConditioner produceAirConditioner() { return new HaierAirConditioner(); } }
TCLFactory類
package abstractfactory; public class TCLFactory implements EFactory { @Override public Television produceTelevision() { return new TCLTelevision(); } @Override public AirConditioner produceAirConditioner() { return new TCLAirConditioner(); } }
AbstractFactoryconfig.xml
<?xml version="1.0" encoding="UTF-8"?> <config> <className>abstractfactory.HaierFactory</className> </config>
XMLUtil類
package abstractfactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; public class XMLUtil { //該方法用於從XML配置文件中提取具體類類名,並返回一個實例對象 public static Object getBean(){ try { //創建文檔對象 DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dFactory.newDocumentBuilder(); Document doc; doc = builder.parse(new File("D:\\MyNewWorld\\Study_JAVA\\MyHome\\Write_java\\My_Maven\\src\\main\\resources\\AbstractFactoryconfig.xml")); //獲取包含類名的文本節點 NodeList n1 = doc.getElementsByTagName("className"); Node classNode = n1.item(0).getFirstChild(); String cName = classNode.getNodeValue(); //通過類名生成實例對象並將其返回 Class c = Class.forName(cName); Object obj = c.newInstance(); return obj; } catch (Exception e) { e.printStackTrace(); return null; } } }
Client類
package abstractfactory; public class Client { public static void main(String[] args) { try{ EFactory factory; Television tv; AirConditioner ac; factory = (EFactory) XMLUtil.getBean(); tv = factory.produceTelevision(); tv.play(); ac = factory.produceAirConditioner(); ac.changeTemperature(); }catch (Exception e){ System.out.println(e.getMessage()); } } }
運行結果

模式效果與應用
抽象工廠模式優點:
- 隔離了具體類的生成,使得客戶端並不需要知道什么被創建
- 當一個產品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的對象
- 增加新的產品族很方便,無需修改已有系統,符合開閉原則
抽象工廠模式缺點:
- 增加新的產品等級結構麻煩,需要對原有系統進行較大的修改,甚至需要修改抽象層代碼,這顯然會帶來較大的不便,違背了開閉原則。
在以下情況下可以使用抽象工廠模式:
- 一個系統不應當依賴於產品類實例如何被創建、組合和表達的細節
- 系統中有多於一個的產品族,但每次只使用其中某一產品族
- 屬於同一個產品族的產品將在一起使用,這一約束必須在系統的設計中體現出來。
- 產品等級結構穩定,在設計完成之后不會向系統中增加新的產品等級結構或者刪除已有的產品等級結構。