工廠模式提供了一種創建對象的最佳方式。在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,并且是通過使用一個共同的接口來指向新創建的對象。實現了創建者和調用者分離,工廠模式分為簡單工廠、工廠方法、抽象工廠模式。
簡單工廠模式又叫靜態方法模式(因為工廠類定義了一個靜態方法)現實生活中,工廠是負責生產產品的;同樣在設計模式中,簡單工廠模式我們可以理解為負責生產對象的一個類,稱為“工廠類”。
將“類實例化的操作”與“使用對象的操作”分開,讓使用者不用知道具體參數就可以實例化出所需要的“產品”類,從而避免了在客戶端代碼中顯式指定,實現了解耦。即使用者可直接消費產品而不需要知道其生產的細節
簡單工廠模式:把對象的創建放到一個工廠類中,通過參數來創建不同的對象。
/**
* 簡單工廠類
*/
public class SimpleFactory {
/**
* 生產工廠
*/
public static OSSConfig createOSSConfig(String name) {
OSSConfig config = null;
switch (name) {
case "alibaba":
config = new AlibabaOSSConfig();
break;
case "tencent":
config = new TencentOSSConfig();
break;
default:
break;
}
return config;
}
}
將創建實例的工作與使用實例的工作分開,使用者不必關心類對象如何創建,實現了解耦;
把初始化實例時的工作放到工廠里進行,使代碼更容易維護。 更符合面向對象的原則 & 面向接口編程,而不是面向實現編程。
1)工廠類集中了所有實例(產品)的創建邏輯,一旦這個工廠不能正常工作,整個系統都會受到影響;
2)違背“開放 - 關閉原則”,一旦添加新產品就不得不修改工廠類的邏輯,這樣就會造成工廠邏輯過于復雜。
3)簡單工廠模式由于使用了靜態工廠方法,靜態方法不能被繼承和重寫,會造成工廠角色無法形成基于繼承的等級結構。
客戶如果只知道傳入工廠類的參數,對于如何創建對象的邏輯不關心時;
當工廠類負責創建的對象(具體產品)比較少時。
工廠方法模式,又稱工廠模式、多態工廠模式和虛擬構造器模式,通過定義工廠父類負責定義創建對象的公共接口,而子類則負責生成具體的對象。
工廠方法模式: 每種產品由一種工廠來創建,一個工廠處理一個對象。
角色組成
1. 抽象工廠: 定義工廠類所具有的基本的操作
2. 具體工廠:該類必須繼承抽象工廠,實現抽象工廠定義的方法,返回一個對象
3. 抽象產品:定義了抽象產品具有的基本操作
4. 產品實現類:實現抽象產品類對定義的抽象方法,和具體工廠一一對應;
/**
* 抽象產品: 配置接口
*/
interface OSSConfig {
/**
* 初始化OSS配置
*/
void init();
}
/**
* 具體產品: 阿里云OSS配置
*/
class AlibabaOSSConfig implements OSSConfig {
@Override
public void init() {
System.out.println("初始化--阿里云--OSS配置");
}
}
/**
* 具體產品: 騰訊云OSS配置
*/
class TencentOSSConfig implements OSSConfig {
@Override
public void init() {
System.out.println("初始化--騰訊云--OSS配置");
}
}
/**
* 抽象工廠
*/
interface Factory {
OSSConfig createOSSConfig();
}
/**
* 具體工廠: 騰訊云工廠
*/
class TencentOSSFactory implements Factory {
@Override
public OSSConfig createOSSConfig() {
return new TencentOSSConfig();
}
}
/**
* 具體工廠: 阿里云工廠
*/
class AlibabaOSSFactory implements Factory {
@Override
public OSSConfig createOSSConfig() {
return new AlibabaOSSConfig();
}
}
/**
* 工廠設計模擬類
*/
public class FactoryMethod {
public static void main(String[] args) {
AlibabaOSSFactory alibabaOSSFactory = new AlibabaOSSFactory();
OSSConfig alibabaConifg = alibabaOSSFactory.createOSSConfig();
alibabaConifg.init();
TencentOSSFactory tencentOSSFactory = new TencentOSSFactory();
OSSConfig tencentConfig = tencentOSSFactory.createOSSConfig();
tencentConfig.init();
}
}
工廠方法模式把具體產品的創建推遲到工廠類的子類(具體工廠)中,此時工廠類不再負責所有產品的創建,而只是給出具體工廠必須實現的接口,這樣工廠方法模式在添加新產品的時候就不修改工廠類邏輯而是添加新的工廠子類,符合開放封閉原則,克服了簡單工廠模式中缺點。
1)更符合開-閉原則
新增一種產品時,只需要增加相應的具體產品類和相應的工廠子類即可
簡單工廠模式需要修改工廠類的判斷邏輯
2)符合單一職責原則
每個具體工廠類只負責創建對應的產品
簡單工廠中的工廠類存在復雜的switch邏輯判斷
3)不使用靜態工廠方法,可以形成基于繼承的等級結構。
簡單工廠模式的工廠類使用靜態工廠方法
總結:工廠模式可以說是簡單工廠模式的進一步抽象和拓展,在保留了簡單工廠的封裝優點的同時,讓擴展變得簡單,讓繼承變得可行,增加了多態性的體現。
1)添加新產品時,除了增加新產品類外,還要提供與之對應的具體工廠類,系統類的個數將成對增加,在一定程度上增加了系統的復雜度;同時,有更多的類需要編譯和運行,會給系統帶來一些額外的開銷;
2)由于考慮到系統的可擴展性,需要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增加了系統的抽象性和理解難度,且在實現時可能需要用到DOM、反射等技術,增加了系統的實現難度。
3)雖然保證了工廠方法內的對修改關閉,但對于使用工廠方法的類,如果要更換另外一種產品,仍然需要修改實例化的具體工廠類;一個具體工廠只能創建一種具體產品。
1)當一個類不知道它所需要的對象的類時,在工廠方法模式中,客戶端不需要知道具體產品類的類名,只需要知道所對應的工廠即可;
2)當一個類希望通過其子類來指定創建對象時,在工廠方法模式中,對于抽象工廠類只需要提供一個創建產品的接口,而由其子類來確定具體要創建的對象,利用面向對象的多態性和里氏代換原則,在程序運行時,子類對象將覆蓋父類對象,從而使得系統更容易擴展。
3)將創建對象的任務委托給多個工廠子類中的某一個,客戶端在使用時可以無須關心是哪一個工廠子類創建產品子類,需要時再動態指定,可將具體工廠類的類名存儲在配置文件或數據庫中。
抽象工廠模式,即Abstract Factory Pattern,提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們具體的類;具體的工廠負責實現具體的產品實例。 允許使用抽象的接口來創建一組相關產品,而不需要知道或關心實際生產出的具體產品是什么,這樣就可以從具體產品中被解耦。
抽象工廠模式:工廠方法模式的進一步延伸。
角色組成
1. 抽象工廠: 定義工廠類所具有的基本的操作
2. 具體工廠:具體工廠實現了抽象工廠,每個工廠方法返回多個具體對象
3. 抽象類接口:定義了產品具有的基本操作,提供一組所有類都具有的業務方法
4. 抽象類:用于實現抽象接口所定義的業務方法,只做抽象接口,具體由產品實現類處理
5. 產品實現類:實現抽象產品類對定義的抽象方法,和具體工廠一對多;
/**
* 抽象產品: 配置接口
*/
interface OSSConfig {
/**
* 初始化OSS配置
*/
void init();
}
/**
* 具體產品: 阿里云OSS配置
*/
abstract class AlibabaOSSConfig implements OSSConfig {
public abstract void init();
}
/**
* 具體產品: 阿里云OSS配置Test環境
*/
class AlibabaTstOSSConfig extends AlibabaOSSConfig {
@Override
public void init() {
System.out.println("初始化--阿里云--test環境--OSS配置");
}
}
/**
* 具體產品: 阿里云OSS配置生產環境
*/
class AlibabaPreOSSConfig extends AlibabaOSSConfig {
@Override
public void init() {
System.out.println("初始化--阿里云--Pre環境--OSS配置");
}
}
/**
* 抽象產品: 騰訊云OSS配置
*/
abstract class TencentOSSConfig implements OSSConfig {
public abstract void init();
}
/**
* 抽象產品: 騰訊云OSS配置
*/
class TencentProOSSConfig extends TencentOSSConfig {
@Override
public void init() {
System.out.println("初始化--騰訊云--Pre環境--OSS配置");
}
}
/**
* 抽象工廠
*/
interface Factory {
/**
* 獲取測試環境配置
*/
OSSConfig createOSSTestConfig();
/**
* 獲取生成環境配置
*/
OSSConfig createOSSPreConfig();
}
/**
* 具體工廠: 騰訊云工廠
*/
class TencentOSSFactory implements Factory {
@Override
public OSSConfig createOSSTestConfig() {
return null;
}
@Override
public OSSConfig createOSSPreConfig() {
return new TencentProOSSConfig();
}
}
/**
* 具體工廠: 騰訊云工廠
*/
class AlibabaOSSFactory implements Factory {
@Override
public OSSConfig createOSSTestConfig() {
return new AlibabaTstOSSConfig();
}
@Override
public OSSConfig createOSSPreConfig() {
return new AlibabaPreOSSConfig();
}
}
/**
* 工廠設計模擬類
* 產品接口可以定義OSS配置的操作接口,不同的廠商實現都去實現接口,通過工廠動態生成配置
*/
public class AbstractFactory {
public static void main(String[] args) {
// 阿里云oss配置
AlibabaOSSFactory alibabaOSSFactory = new AlibabaOSSFactory();
OSSConfig alibabaConifg = alibabaOSSFactory.createOSSPreConfig();
alibabaConifg.init();
OSSConfig alibabaTestConifg = alibabaOSSFactory.createOSSTestConfig();
alibabaTestConifg.init();
// 騰云云oss配置
TencentOSSFactory tencentOSSFactory = new TencentOSSFactory();
OSSConfig tencentConifg = tencentOSSFactory.createOSSPreConfig();
tencentConifg.init();
}
}
1)降低耦合
抽象工廠模式將具體產品的創建延遲到具體工廠的子類中,這樣將對象的創建封裝起來,可以減少客戶端與具體產品類之間的依賴,從而使系統耦合度低,這樣更有利于后期的維護和擴展;
2)更符合開-閉原則
新增一種產品類時,只需要增加相應的具體產品類和相應的工廠子類即可
3)符合單一職責原則
每個具體工廠類只負責創建對應的產品
4)不使用靜態工廠方法,可以形成基于繼承的等級結構。
抽象工廠模式很難支持新種類產品的變化。這是因為抽象工廠接口中已經確定了可以被創建的產品集合,如果需要添加新產品,此時就必須去修改抽象工廠的接口,這樣就涉及到抽象工廠類的以及所有子類的改變,這樣也就違背了“開發——封閉”原則。
1)一個系統不要求依賴產品類實例如何被創建、組合和表達的表達,這點也是所有工廠模式應用的前提。
2)這個系統有多個系列產品,而系統中只消費其中某一系列產品
3)系統要求提供一個產品類的庫,所有產品以同樣的接口出現,客戶端不需要依賴具體實現。
工廠方法模式:具體工廠類只能創建一個具體產品類的實例。
抽象工廠模式:具體工廠類可以創建多個具體產品類的實例。