抽象工厂模式(JAVA反射)
生活随笔
收集整理的這篇文章主要介紹了
抽象工厂模式(JAVA反射)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
實例代碼(JAVA):模式動機
在工廠方法模式中具體工廠負責生產(chǎn)具體的產(chǎn)品,每一個具體工廠對應一種具體產(chǎn)品,工廠方法也具有唯一性,一般情況下,一個具體工廠中只有一個工廠方法或者一組重載的工廠方法。但是有時候我們需要一個工廠可以提供多個產(chǎn)品對象,而不是單一的產(chǎn)品對象。 為了更清晰地理解工廠方法模式,需要先引入兩個概念: ??產(chǎn)品等級結構:產(chǎn)品等級結構即產(chǎn)品的繼承結構,如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構成了一個產(chǎn)品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。 ??產(chǎn)品族:在抽象工廠模式中,產(chǎn)品族是指由同一個工廠生產(chǎn)的,位于不同產(chǎn)品等級結構中的一組產(chǎn)品,如海爾電器工廠生產(chǎn)的海爾電視機、海爾電冰箱,海爾電視機位于電視機產(chǎn)品等級結構中,海爾電冰箱位于電冰箱產(chǎn)品等級結構中。 產(chǎn)品族與產(chǎn)品等級結構示意圖: 當系統(tǒng)所提供的工廠所需生產(chǎn)的具體產(chǎn)品并不是一個簡單的對象,而是多個位于不同產(chǎn)品等級結構中屬于不同類型的具體產(chǎn)品時需要使用抽象工廠模式。 抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態(tài)。 抽象工廠模式與工廠方法模式最大的區(qū)別在于,工廠方法模式針對的是一個產(chǎn)品等級結構,而抽象工廠模式則需要面對多個產(chǎn)品等級結構,一個工廠等級結構可以負責多個不同產(chǎn)品等級結構中的產(chǎn)品對象的創(chuàng)建 。當一個工廠等級結構可以創(chuàng)建出分屬于不同產(chǎn)品等級結構的一個產(chǎn)品族中的所有對象時,抽象工廠模式比工廠方法模式更為簡單、有效率。模式定義
抽象工廠模式(Abstract Factory Pattern):提供一個創(chuàng)建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,屬于對象創(chuàng)建型模式。模式結構
抽象工廠模式包含如下角色: ??AbstractFactory:抽象工廠 ??ConcreteFactory:具體工廠 ??AbstractProduct:抽象產(chǎn)品 ??Product:具體產(chǎn)品模式分析
抽象工廠類的典型代碼如下:
1 public abstract class AbstractFactory 2 { 3 public abstract AbstractProductA createProductA(); 4 public abstract AbstractProductB createProductB(); 5 }?具體工廠類的典型代碼如下:
1 public class ConcreteFactory1 extends AbstractFactory 2 { 3 public AbstractProductA createProductA() 4 { 5 return new ConcreteProductA1(); 6 } 7 public AbstractProductB createProductB() 8 { 9 return new ConcreteProductB1(); 10 } 11 }?
模式實例與解析
實例一:電器工廠 ??一個電器工廠可以產(chǎn)生多種類型的電器,如海爾工廠可以生產(chǎn)海爾電視機、海爾空調等,TCL工廠可以生產(chǎn)TCL電視機、TCL空調等,相同品牌的電器構成一個產(chǎn)品族,而相同類型的電器構成了一個產(chǎn)品等級結構,現(xiàn)使用抽象工廠模式模擬該場景。實例代碼(JAVA):
1 //抽象產(chǎn)品 Television 2 public interface Television 3 { 4 public void play(); 5 } 6 7 //具體產(chǎn)品 HaierTelevision 8 public class HaierTelevision implements Television 9 { 10 public void play() 11 { 12 System.out.println("海爾電視機播放中......"); 13 } 14 } 15 16 //具體產(chǎn)品 TCLTelevision 17 public class TCLTelevision implements Television 18 { 19 public void play() 20 { 21 System.out.println("TCL電視機播放中......"); 22 } 23 } 24 25 //抽象產(chǎn)品 AirConditioner 26 public interface AirConditioner 27 { 28 public void changeTemperature(); 29 } 30 31 //具體產(chǎn)品 HaierAirConditioner 32 public class HaierAirConditioner implements AirConditioner 33 { 34 public void changeTemperature() 35 { 36 System.out.println("海爾空調溫度改變中......"); 37 } 38 } 39 40 //具體產(chǎn)品 TCLAirConditioner 41 public class TCLAirConditioner implements AirConditioner 42 { 43 public void changeTemperature() 44 { 45 System.out.println("TCL空調溫度改變中......"); 46 } 47 } 48 49 //抽象工廠 EFactory 50 public interface EFactory 51 { 52 public Television produceTelevision(); 53 public AirConditioner produceAirConditioner(); 54 } 55 56 //具體工廠 HaierFactory 57 public class HaierFactory implements EFactory 58 { 59 public Television produceTelevision() 60 { 61 return new HaierTelevision(); 62 } 63 64 public AirConditioner produceAirConditioner() 65 { 66 return new HaierAirConditioner(); 67 } 68 } 69 70 //具體工廠 TCLFactory 71 public class TCLFactory implements EFactory 72 { 73 public Television produceTelevision() 74 { 75 return new TCLTelevision(); 76 } 77 78 public AirConditioner produceAirConditioner() 79 { 80 return new TCLAirConditioner(); 81 } 82 } 83 84 //配置文件 config.xml 85 <?xml version="1.0"?> 86 <config> 87 <className>HaierFactory</className> 88 </config> 89 90 //通過反射獲得具體工廠的實例 XMLUtil 91 import javax.xml.parsers.*; 92 import org.w3c.dom.*; 93 import org.xml.sax.SAXException; 94 import java.io.*; 95 public class XMLUtil 96 { 97 //該方法用于從XML配置文件中提取具體類類名,并返回一個實例對象 98 public static Object getBean() 99 { 100 try 101 { 102 //創(chuàng)建文檔對象 103 DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); 104 DocumentBuilder builder = dFactory.newDocumentBuilder(); 105 Document doc; 106 doc = builder.parse(new File("config.xml")); 107 108 //獲取包含類名的文本節(jié)點 109 NodeList nl = doc.getElementsByTagName("className"); 110 Node classNode=nl.item(0).getFirstChild(); 111 String cName=classNode.getNodeValue(); 112 113 //通過類名生成實例對象并將其返回 114 Class c=Class.forName(cName); 115 Object obj=c.newInstance(); 116 return obj; 117 } 118 catch(Exception e) 119 { 120 e.printStackTrace(); 121 return null; 122 } 123 } 124 } 125 126 //客戶端類 Client 127 public class Client 128 { 129 public static void main(String args[]) 130 { 131 try 132 { 133 EFactory factory; 134 Television tv; 135 AirConditioner ac; 136 factory=(EFactory)XMLUtil.getBean(); 137 tv=factory.produceTelevision(); 138 tv.play(); 139 ac=factory.produceAirConditioner(); 140 ac.changeTemperature(); 141 } 142 catch(Exception e) 143 { 144 System.out.println(e.getMessage()); 145 } 146 } 147 }?實例代碼(C++):
1 // 抽象工廠模式 2 #include <iostream> 3 using namespace std; 4 5 //抽象產(chǎn)品類 Television 6 class Television 7 { 8 public: 9 virtual void play() = 0; 10 }; 11 12 //具體產(chǎn)品類 HaierTelevision 13 class HaierTelevision:public Television 14 { 15 public: 16 void play() override 17 { 18 cout << "海爾電視播放中..." << endl; 19 } 20 }; 21 22 //具體產(chǎn)品類 TCLTelevision 23 class TCLTelevision : public Television 24 { 25 public: 26 void play() override 27 { 28 cout << "TCL電視播放中..." << endl; 29 } 30 }; 31 32 //抽象產(chǎn)品 AirConditioner 33 class AirConditioner 34 { 35 public: 36 virtual void changeTemperature() = 0; 37 }; 38 39 //具體產(chǎn)品 HaierAirConditioner 40 class HaierAirConditioner : public AirConditioner 41 { 42 public: 43 void changeTemperature() override 44 { 45 cout << "海爾空調溫度改變中..." << endl; 46 } 47 }; 48 49 //具體產(chǎn)品 TCLAirConditioner 50 class TCLAirConditioner : public AirConditioner 51 { 52 public: 53 void changeTemperature() override 54 { 55 cout << "TCL空調溫度改變中..." << endl; 56 } 57 }; 58 59 //抽象工廠 EFactory 60 class EFactory 61 { 62 public: 63 virtual Television* productTelevision() = 0; 64 virtual AirConditioner* productAirConditioner() = 0; 65 }; 66 67 //具體工廠 HaierFactory 68 class HaierFactory : public EFactory 69 { 70 public: 71 Television* productTelevision() override 72 { 73 return new HaierTelevision(); 74 } 75 76 AirConditioner* productAirConditioner() override 77 { 78 return new HaierAirConditioner(); 79 } 80 }; 81 82 //具體工廠 TCLFactory 83 class TCLFactory : public EFactory 84 { 85 public: 86 Television* productTelevision() override 87 { 88 return new TCLTelevision(); 89 } 90 91 AirConditioner* productAirConditioner() override 92 { 93 return new TCLAirConditioner(); 94 } 95 }; 96 97 //客戶端 98 int main() 99 { 100 EFactory* factory; 101 Television* tv; 102 AirConditioner* ac; 103 factory = new HaierFactory(); 104 tv = factory->productTelevision(); 105 tv->play(); 106 ac = factory->productAirConditioner(); 107 ac->changeTemperature(); 108 109 factory = new TCLFactory(); 110 tv = factory->productTelevision(); 111 tv->play(); 112 ac = factory->productAirConditioner(); 113 ac->changeTemperature(); 114 return 0; 115 }?
運行結果: 實例二:數(shù)據(jù)庫操作工廠 ? 某系統(tǒng)為了改進數(shù)據(jù)庫操作的性能,自定義數(shù)據(jù)庫連接對象Connection和語句對象Statement,可針對不同類型的數(shù)據(jù)庫提供不同的連接對象和語句對象,如提供Oracle或SQL Server專用連接類和語句類,而且用戶可以通過配置文件等方式根據(jù)實際需要動態(tài)更換系統(tǒng)數(shù)據(jù)庫。使用抽象工廠模式設計該系統(tǒng)。模式優(yōu)缺點
優(yōu)點 ??抽象工廠模式隔離了具體類的生成,使得客戶并不需要知道什么被創(chuàng)建。由于這種隔離,更換一個具體工廠就變得相對容易。所有的具體工廠都實現(xiàn)了抽象工廠中定義的那些公共接口,因此只需改變具體工廠的實例,就可以在某種程度上改變整個軟件系統(tǒng)的行為。另外,應用抽象工廠模式可以實現(xiàn)高內聚低耦合的設計目的,因此抽象工廠模式得到了廣泛的應用。 ??當一個產(chǎn)品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象。這對一些需要根據(jù)當前環(huán)境來決定其行為的軟件系統(tǒng)來說,是一種非常實用的設計模式。 ??增加新的具體工廠和產(chǎn)品族很方便,無須修改已有系統(tǒng),符合“開閉原則”。 缺點 ? 在添加新的產(chǎn)品對象時,難以擴展抽象工廠來生產(chǎn)新種類的產(chǎn)品,這是因為在抽象工廠角色中規(guī)定了所有可能被創(chuàng)建的產(chǎn)品集合,要支持新種類的產(chǎn)品就意味著要對該接口進行擴展,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來較大的不便。 ? 開閉原則的傾斜性(增加新的工廠和產(chǎn)品族容易,增加新的產(chǎn)品等級結構麻煩)模式適用環(huán)境
在以下情況下可以使用抽象工廠模式: ? 一個系統(tǒng)不應當依賴于產(chǎn)品類實例如何被創(chuàng)建、組合和表達的細節(jié),這對于所有類型的工廠模式都是重要的。 ? 系統(tǒng)中有多于一個的產(chǎn)品族,而每次只使用其中某一產(chǎn)品族。 ? 屬于同一個產(chǎn)品族的產(chǎn)品將在一起使用,這一約束必須在系統(tǒng)的設計中體現(xiàn)出來。 ? 系統(tǒng)提供一個產(chǎn)品類的庫,所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于具體實現(xiàn)。模式應用
(1) Java SE AWT(抽象窗口工具包) ? 在Java語言的AWT(抽象窗口工具包)中就使用了抽象工廠模式,它使用抽象工廠模式來實現(xiàn)在不同的操作系統(tǒng)中應用程序呈現(xiàn)與所在操作系統(tǒng)一致的外觀界面。 (2) 在很多軟件系統(tǒng)中需要更換界面主題,要求界面中的按鈕、文本框、背景色等一起發(fā)生改變時,可以使用抽象工廠模式進行設計。模式擴展
“開閉原則”的傾斜性 ? “開閉原則”要求系統(tǒng)對擴展開放,對修改封閉,通過擴展達到增強其功能的目的。對于涉及到多個產(chǎn)品族與多個產(chǎn)品等級結構的系統(tǒng),其功能增強包括兩方面: ? (1) 增加產(chǎn)品族:對于增加新的產(chǎn)品族,工廠方法模式很好的支持了“開閉原則”,對于新增加的產(chǎn)品族,只需要對應增加一個新的具體工廠即可,對已有代碼無須做任何修改。 ? (2) 增加新的產(chǎn)品等級結構:對于增加新的產(chǎn)品等級結構,需要修改所有的工廠角色,包括抽象工廠類,在所有的工廠類中都需要增加生產(chǎn)新產(chǎn)品的方法,不能很好地支持“開閉原則”。 ? 抽象工廠模式的這種性質稱為“開閉原則”的傾斜性,抽象工廠模式以一種傾斜的方式支持增加新的產(chǎn)品,它為新產(chǎn)品族的增加提供方便,但不能為新的產(chǎn)品等級結構的增加提供這樣的方便。 工廠模式的退化 ? 當抽象工廠模式中每一個具體工廠類只創(chuàng)建一個產(chǎn)品對象,也就是只存在一個產(chǎn)品等級結構時,抽象工廠模式退化成工廠方法模式;當工廠方法模式中抽象工廠與具體工廠合并,提供一個統(tǒng)一的工廠來創(chuàng)建產(chǎn)品對象,并將創(chuàng)建對象的工廠方法設計為靜態(tài)方法時,工廠方法模式退化成簡單工廠模式。轉載于:https://www.cnblogs.com/WindSun/p/10253248.html
總結
以上是生活随笔為你收集整理的抽象工厂模式(JAVA反射)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF实战案例-打印
- 下一篇: LUOGU P4587 [FJOI201