《設計模式》(GoF) 明確將 Factory Method 歸類為 Class Creational Pattern(類創建型模式),其本質是將對象創建推遲到子類,通過繼承實現,屬於靜態、編譯時確定的關係。而 Abstract Factory 屬於 Object Creational Pattern(對象創建型),通過組合/委派實現,屬於動態、運行時確定。閻宏《Java與模式》第 167 頁結構圖及示例代碼,卻呈現出「客戶端直接實例化 ConcreteCreator 並調用 factory()」的形式,這實際上將工廠方法變成了對象創建模式,與 GoF 原意存在根本偏差。
// 抽象產品
abstract class Document {
abstract void open(); void close(); abstract void save();
}
// 具體產品
class MyDocument extends Document { ... }
// Creator (抽象工廠角色) —— 關鍵:包含模板方法 anOperation()
abstract class Application {
// 工廠方法:由子類實現
protected abstract Document createDocument();
// 模板方法:定義業務流程骨架,調用工廠方法
public final void newDocument() {
Document doc = createDocument(); // 此處綁定子類創建邏輯
doc.open();
// ... 其他通用流程
doc.save();
}
}
// ConcreteCreator
class MyApplication extends Application {
protected Document createDocument() {
return new MyDocument(); // 創建邏輯固化在子類中
}
}
關鍵點:Application 中的 anOperation() (即示例中的 newDocument()) 是模板方法,它調用 factoryMethod() 獲取產品。客戶端代碼應為:
Application app = new MyApplication(); // 編譯時確定具體工廠
app.newDocument(); // 觸發流程,內部自動調用 createDocument()
而非《Java與模式》示例中的:
Creator creator = new ConcreteCreator1();
Product prod = creator.factory(); // 直接調用工廠方法,像用對象一樣用工廠
| 維度 | GoF Factory Method (類創建型) | 《Java與模式》示例 (實際為對象創建型) |
|---|---|---|
| 創建職責承擔者 | Creator 的子類 (通過繼承) | 獨立的 Creator 實例 (通過組合/調用) |
| 綁定時機 | 編譯時 (new MyApplication()) | 運行時 (可動態換 ConcreteCreator) |
| 模板方法角色 | 核心:anOperation() 封裝流程,強制使用工廠方法 | 缺失:接口僅有 factory(),無業務流程封裝 |
| 靈活性代價 | 靜態,換工廠需改實例化代碼 | 動態,但喪失了「流程標準化」的模板方法優勢 |
AnOperation() 和 FactoryMethod() 兩個方法,前者調用後者。《Java與模式》圖省略了 AnOperation(),切斷了模板方法與工廠方法的內在聯繫。// 框架層:定義不可變的文檔處理流程
public abstract class DocumentEditor {
// 模板方法:最終方法,禁止覆寫
public final void createNewDocument() {
Document doc = createDocument(); // 委派給子類創建
doc.open();
setupDefaultStyles(doc);
doc.save();
}
// 工廠方法:受保護,強制子類實現
protected abstract Document createDocument();
private void setupDefaultStyles(Document doc) { ... }
}
// 應用層:具體化創建邏輯
public class TextEditor extends DocumentEditor {
protected Document createDocument() {
return new TextDocument(); // 只關心創建什麼文檔
}
}
// 客戶端:面向抽象編程
public class Main {
public static void main(String[] args) {
DocumentEditor editor = new TextEditor(); // 編譯時綁定
editor.createNewDocument(); // 觸發標準化流程
}
}
設計模式的精髓在於意圖與結構的協同。Factory Method 的靈魂是「模板方法 + 工廠方法」的雙重奏——前者管控流程,後者解耦創建。任何省略模板方法、將工廠方法暴露為普通接口方法供客戶端直接調用的示例,都淡化了模式的核心價值,易導致學習者混淆「類創建型」與「對象創建型」的本質界限。建議研讀 GoF 原著第 107-116 頁,對照類圖與代碼,體會「繼承實現創建」與「委派實現創建」的深層差異。