抽象工廠模式(Abstract Factory Pattern)詳解
一、抽象工廠模式簡介
抽象工廠模式(Abstract Factory Pattern) 是一種 創建型設計模式(對象創建型模式),它提供了一種創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
抽象工廠模式的核心在于“抽象”,通過定義一個創建對象的接口,但由子類決定要實例化的類是哪一個。
你可以這樣理解:
“抽象工廠就像是一個‘品牌制造商’,根據不同的需求生產出不同品牌的同類產品(如手機、電腦),每個品牌的產品都是相關的,但具體實現各有特色。”
工廠方法模式
每個具體工廠只有一個或者一組重載的工廠方法,只能生產一種產品,可能會導致系統中存在大量的工廠類,勢必會增加系統的開銷
抽象工廠模式
一個工廠可以生產一系列產品(一族產品),極大減少了工廠類的數量
產品等級結構:產品等級結構即產品的繼承結構
產品族:產品族是指由同一個工廠生產的,位于不同產品等級結構中的一組產品
當系統所提供的工廠生產的具體產品并不是一個簡單的對象,而是多個位于不同產品等級結構、屬于不同類型的具體產品時就可以使用抽象工廠模式。
抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形式。
又稱為工具(Kit)模式。
抽象工廠模式中的具體工廠不只是創建一種產品,它負責創建一族產品。
當一個工廠等級結構可以創建出分屬于不同產品等級結構的一個產品族中的所有對象時,抽象工廠模式比工廠方法模式更為簡單、更有效率。
抽象工廠模式包含以下4個角色:
AbstractFactory(抽象工廠)
ConcreteFactory(具體工廠)
AbstractProduct(抽象產品)
ConcreteProduct(具體產品)
二、解決的問題類型
抽象工廠模式主要用于解決以下問題:
- 需要創建一系列相關對象:這些對象通常是一起使用的,例如一套圖形界面組件(按鈕、文本框等)。
- 希望隱藏具體產品的創建邏輯:避免客戶端直接使用
new
關鍵字來實例化具體類。 - 支持擴展性:新增產品族時只需添加新的具體工廠和產品實現,無需修改已有代碼。
三、使用場景
場景 | 示例 |
---|---|
UI 組件庫 | 如 Windows 和 Mac 系統下的按鈕、窗口等組件 |
數據庫連接池 | 提供多種數據庫的連接管理(MySQL, PostgreSQL 等) |
游戲中的角色裝備系統 | 不同等級的角色擁有不同級別的武器和防具 |
一個系統不應當依賴于產品類實例如何被創建、組合和表達的細節。
系統中有多于一個的產品族,但每次只使用其中某一產品族。
屬于同一個產品族的產品將在一起使用,這一約束必須在系統的設計中體現出來。
產品等級結構穩定,設計完成之后,不會向系統中增加新的產品等級結構或者刪除已有的產品等級結構。
四、核心概念
- AbstractFactory(抽象工廠):聲明一組用于創建抽象產品的方法。
- ConcreteFactory(具體工廠):實現抽象工廠中定義的方法,負責創建具體產品對象。
- AbstractProduct(抽象產品):為每類產品定義接口或基類。
- ConcreteProduct(具體產品):實現抽象產品接口的具體類。
五、實際代碼案例(Java)
我們以“跨平臺UI組件”為例,演示抽象工廠模式的應用。假設我們需要在Windows和MacOS平臺上顯示按鈕和文本框。
1. 定義抽象產品接口
// 按鈕接口
public interface Button {void paint();
}// 文本框接口
public interface TextBox {void displayText(String text);
}
2. 創建具體產品類
// Windows風格按鈕
public class WindowsButton implements Button {@Overridepublic void paint() {System.out.println("繪制 Windows 樣式的按鈕");}
}// MacOS風格按鈕
public class MacOSButton implements Button {@Overridepublic void paint() {System.out.println("繪制 MacOS 樣式的按鈕");}
}// Windows風格文本框
public class WindowsTextBox implements TextBox {@Overridepublic void displayText(String text) {System.out.println("在 Windows 樣式的文本框中顯示: " + text);}
}// MacOS風格文本框
public class MacOSTextBox implements TextBox {@Overridepublic void displayText(String text) {System.out.println("在 MacOS 樣式的文本框中顯示: " + text);}
}
3. 定義抽象工廠接口
// GUI工廠接口
public interface GUIFactory {Button createButton();TextBox createTextBox();
}
4. 創建具體工廠類
// Windows風格GUI工廠
public class WindowsFactory implements GUIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic TextBox createTextBox() {return new WindowsTextBox();}
}// MacOS風格GUI工廠
public class MacOSFactory implements GUIFactory {@Overridepublic Button createButton() {return new MacOSButton();}@Overridepublic TextBox createTextBox() {return new MacOSTextBox();}
}
5. 客戶端測試類
public class Client {private Button button;private TextBox textBox;public Client(GUIFactory factory) {button = factory.createButton();textBox = factory.createTextBox();}public void render() {button.paint();textBox.displayText("Hello World!");}public static void main(String[] args) {String platform = "Windows"; // 假設當前平臺為WindowsGUIFactory factory;if (platform.equals("Windows")) {factory = new WindowsFactory();} else {factory = new MacOSFactory();}Client app = new Client(factory);app.render();}
}
輸出結果(假設平臺為Windows):
繪制 Windows 樣式的按鈕
在 Windows 樣式的文本框中顯示: Hello World!
典型代碼
典型的抽象工廠類代碼:
abstract class AbstractFactory
{
public abstract AbstractProductA CreateProductA(); //工廠方法一
public abstract AbstractProductB CreateProductB(); //工廠方法二
……
}
典型的具體工廠類代碼:
class ConcreteFactory1 : AbstractFactory
{//工廠方法一
public override AbstractProductA CreateProductA()
{return new ConcreteProductA1();
}
//工廠方法二
public override AbstractProductB CreateProductB()
{return new ConcreteProductB1();
}
……
}
其他案例
- 某軟件公司要開發一套界面皮膚庫,可以對基于.NET平臺的桌面軟件進行界面美化。用戶在使用時可以通過菜單來選擇皮膚,不同的皮膚將提供視覺效果不同的按鈕、文本框、組合框等界面元素,例如春天(Spring)風格的皮膚將提供淺綠色的按鈕、綠色邊框的文本框和綠色邊框的組合框,而夏天(Summer)風格的皮膚則提供淺藍色的按鈕、藍色邊框的文本框和藍色邊框的組合框,其結構示意圖如下圖所示:
該皮膚庫需要具備良好的靈活性和可擴展性,用戶可以自由選擇不同的皮膚,開發人員可以在不修改既有代碼的基礎上增加新的皮膚。
現使用抽象工廠模式來設計該界面皮膚庫。
- 電器工廠
一個電器工廠可以產生多種類型的電器,如海爾工廠可以生產海爾電視機、海爾空調等,TCL工廠可以生產TCL電視機、TCL空調等,相同品牌的電器構成一個產品族,而相同類型的電器構成了一個產品等級結構,現使用抽象工廠模式模擬該場景
- 數據庫操作工廠
某系統為了改進數據庫操作的性能,自定義數據庫連接對象Connection和語句對象Statement,可針對不同類型的數據庫提供不同的連接對象和語句對象,如提供Oracle或SQL Server專用連接類和語句類,而且用戶可以通過配置文件等方式根據實際需要動態更換系統數據庫。使用抽象工廠模式設計該系統。
六、優缺點分析
優點 | 描述 |
---|---|
? 統一接口 | 通過抽象層隔離了具體產品的創建過程,使得客戶端僅需知道抽象接口即可 |
? 易于擴展 | 新增產品族時只需添加新的具體工廠和產品實現,不影響現有代碼 |
? 增強靈活性 | 可以輕松切換到不同的產品族 |
缺點 | 描述 |
---|---|
? 增加復雜度 | 引入了額外的抽象層次,可能使系統更加復雜。增加新的產品等級結構麻煩,需要對原有系統進行較大的修改,甚至需要修改抽象層代碼,這顯然會帶來較大的不便,違背了開閉原則 |
? 不便于單獨替換產品 | 更換某一具體產品時可能需要修改所有相關工廠類 |
七、與其他模式對比(補充)
模式名稱 | 目標 |
---|---|
簡單工廠模式 | 通過靜態方法集中創建對象,適用于單一產品族的情況 |
工廠方法模式 | 提供一個創建對象的接口,但由子類決定實例化哪一個類 |
抽象工廠模式 | 創建一系列相關或相互依賴的對象,適合多個產品族的場景 |
八、最終小結
抽象工廠模式是一種強大的創建型設計模式,特別適用于那些需要創建一系列相關對象且希望保持高度靈活性和可擴展性的場景。通過將對象的創建邏輯封裝在抽象工廠中,我們可以有效地分離關注點,提高系統的模塊化程度。
在開發跨平臺應用、多數據庫支持系統、游戲引擎等項目中,抽象工廠模式能夠幫助你更好地組織代碼結構,減少重復代碼,并提高系統的可維護性和可擴展性。
📌 一句話總結:
抽象工廠模式就像一個“產品生產線”,可以根據不同的需求生產出一系列配套的產品,確保產品之間的一致性和兼容性。
? 推薦使用場景:
- 當你需要創建一組相關的對象時;
- 希望將對象創建的邏輯集中在一處進行管理;
- 需要在運行時動態選擇產品族。
擴展
開閉原則的傾斜性
增加產品族
對于增加新的產品族,抽象工廠模式很好地支持了開閉原則,只需要增加具體產品并對應增加一個新的具體工廠,對已有代碼無須做任何修改
增加新的產品等級結構
對于增加新的產品等級結構,需要修改所有的工廠角色,包括抽象工廠類,在所有的工廠類中都需要增加生產新產品的方法,違背了開閉原則