1.簡單工廠模式的定義
簡單工廠模式 (Simple Factory Pattern):定義一個工廠類,內含一個靜態工廠方法,它可以根據參數的不同返回不同類的實例,被創建的實例通常都具有共同的父類。
-
實現簡單,以前寫代碼的時候也經常用這個模式,因爲過於簡單,甚至不是GoF 23個設計模式中的一員…
-
通俗的解釋:Simple Factory模式根據提供給它的數據,返回幾個可能類中的一個類的實例。通常它返回的對象所屬的類都有一個公共的父類和一些公共的方法。
-
它屬於類創簡單工廠模式
-
如果需要什麼對象,只需要傳給工廠類一個正確的參數,就可以獲取到所需要的對象,而無須知道其創建細節。
2.角色分工及結構
- 具體產品類(ConcreteProduct):將需要創建的各種不同產品對象的相關代碼封裝到具體產品類中
- 抽象產品類(Product):將具體產品類公共的代碼進行抽象和提取後封裝在一個抽象產品類中
- 工廠類(Factory):提供一個工廠類用於創建各種產品,在工廠類中提供一個創建產品的工廠方法,該方法可以根據所傳入參數的不同創建不同的具體產品對象
- 客戶端:只需調用工廠類的工廠方法並傳入相應的參數即可得到一個創建型模式
3.優缺點
優點:
- 工廠類含有必要的判斷邏輯,可以決定在什麼時候“創建”哪一個產品類的實例,客戶端可以免除直接創建產品對象的責任,而僅僅“消費”產品。簡單工廠模式通過這種做法實現了對對象創建和使用的分離。
缺點:
- 因爲工廠類集中了所有產品創建邏輯,一旦不能正常工作,整個系統都要受到影響。
- 違反開放/封閉原則: 系統擴展困難,一旦添加新產品就不得不修改工廠邏輯,有可能造成工廠邏輯過於複雜,不利於系統的擴展和維護。
- 另外,簡單工廠模式通常使用靜態工廠方法,這使得無法由子類繼承,造成工廠角色無法形成基於繼承的等級結構。
4.適用環境
- 工廠類負責創建的對象比較少,由於創建的對象較少,不會造成工廠方法中的業務邏輯太過複雜;
- 客戶端只知道傳入工廠類的參數,對於如何創建對象並不關心。
簡單工廠模式的延申----工廠方法模式,繼承了簡單工廠模式的優點,同時還彌補了簡單工廠模式的缺陷,應該是考試的重點把。。
5.工廠方法模式的定義
工廠方法模式:定義一個用於創建對象的接口,但是讓子類決定將哪一個類實例化。工廠方法模式讓一個類的實例化延遲到其子類。
- 類創建模式,其用意是定義一個創建產品對象的工廠接口,將實際創建工作推遲到子類中。
- 工廠方法模式是簡單工廠模式的進一步抽象和推廣。由於使用了多態性,工廠方法模式保持了簡單工廠模式的優點,而且克服了它的缺點。
- 在工廠方法模式中,核心的工廠類不再負責所有產品的創建,而是將具體創建工作交給子類去做。這個核心類僅僅負責給出具體工廠必須實現的接口,而不接觸哪一個產品類被實例化這種細節。這使得工廠方法模式可以允許系統在不修改工廠角色的情況下引進新產品。
- 在Factory Method模式中,工廠類與產品類往往具有平行的等級結構,它們之間一一對應。
6.角色分工及結構
- 抽象工廠(Creator)角色:是工廠方法模式的核心,與應用程序無關。任何在模式中創建對象的具體工廠類必須實現這個接口。
- 具體工廠(Concrete Creator)角色:這是實現抽象工廠接口的具體工廠類,包含與應用程序密切相關的邏輯,並且受到應用程序調用以創建具體產品對象。
- 抽象產品(Product)角色:工廠方法模式所創建的對象的超類,也就是具體產品對象的共同父類或共同擁有的接口。
- 具體產品(Concrete Product)角色:這個角色實現了抽象產品角色所定義的接口。每個具體產品有專門的具體工廠創建,它們之間有一一對應的關係。
7.優缺點
優點
- 模式的核心是一個抽象工廠類,而不是像簡單工廠模式把核心放在一個具體類上;
- 解除了簡單工廠模式中對象創建代碼的耦合,在系統中加入新產品時,完全符合開放/封閉原則。
缺點
- 系統中類的個數將成對增加,在一定程度上增加了系統的複雜度,會給系統帶來一些額外的開銷;
- 增加了系統的抽象性和理解難度;
- 選擇判斷的問題還是存在的,把簡單工廠的內部邏輯判斷移到了客戶端代碼來進行,增加功能時,需要修改客戶端。–可以用配置文件+反射改進
8.適用環境
- 客戶端不知道它所需要的對象的類。在工廠方法模式中,客戶不需要知道具體產品類的類品,只需知道所對應的工廠即可,具體產品對象由具體工廠創建,可將具體工廠類的類名存儲在配置文件或數據庫中。
- 抽象工廠類通過其子類指定創建哪個對象。在工廠方法模式中,對於抽象工廠類只需要提供一個創建產品的接口,而由其子類來確定具體要創建的對象,利用面向對象的多態性和里氏代換原則,在程序運行時,子類對象將覆蓋父類對象,從而使系統更容易擴展。
9.代碼實現
有一個地方一定要記錄一下:通過引入配置文件來解耦(書上用C#寫的,用Java實現一下)
工程結構:
配置文件:
測試類(客戶端):
/**
* 測試類
*/
public class test {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
/*Factory factory;
factory = new BMWCarFactory();
Car car = factory.FactoryMethod();
car.MethodDiff();
factory = new BenzCarFactory();
Car car2 = factory.FactoryMethod();
car2.MethodDiff();*/
//如果需要增加一個新的工廠類,比如說要生產奧迪品牌的車,那麼在客戶端test中仍然需要修改,不符合開閉原則
//下面通過引入配置文件來解決這個問題
Factory carFactory = null;
Car car;
//創建Properties集合對象
Properties prop = new Properties();
//創建一個文件流,加載prop.txt中的內容
prop.load(new FileReader("src/FactorySample/prop.txt"));
// 可以用下面這種方式來獲得prop中所有的鍵,本例中之間用getProperty獲得key
//Set<String> set = prop.stringPropertyNames();
//用value拼出工廠的全類名,FactorySample.BMWCarFactory,這要求工廠的工程路徑要在同一個包下,否則拼的時候太麻煩,還是需要修改類中的內容
String value = "FactorySample." + prop.getProperty("factory");
try {
//利用反射機制獲得工廠類的對象
carFactory = (Factory) Class.forName(value).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
car = carFactory.FactoryMethod();
car.MethodDiff();
}
}
這樣修改工廠的時候只需要修改配置文件就可以了,源碼不需要任何改動