首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

關於《Java與模式》中工廠方法模式示例的商榷

     編輯:Java 相關知識

核心爭議:工廠方法屬於「類創建型」而非「對象創建型」

《設計模式》(GoF) 明確將 Factory Method 歸類為 Class Creational Pattern(類創建型模式),其本質是將對象創建推遲到子類,通過繼承實現,屬於靜態、編譯時確定的關係。而 Abstract Factory 屬於 Object Creational Pattern(對象創建型),通過組合/委派實現,屬於動態、運行時確定。閻宏《Java與模式》第 167 頁結構圖及示例代碼,卻呈現出「客戶端直接實例化 ConcreteCreator 並調用 factory()」的形式,這實際上將工廠方法變成了對象創建模式,與 GoF 原意存在根本偏差。

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(),無業務流程封裝
靈活性代價靜態,換工廠需改實例化代碼動態,但喪失了「流程標準化」的模板方法優勢

為什麼這個區別很重要?

  1. 設計意圖不同:Factory Method 旨在框架定義流程骨架,子類填充具體創建(如文檔編輯器的 New 菜單);而示例演變為「可插拔的創建器」,更接近 Abstract Factory 或 Simple Factory。
  2. 結構圖誤導:GoF 圖 3.1 (第 110 頁) 中 Creator 明確包含 AnOperation() 和 FactoryMethod() 兩個方法,前者調用後者。《Java與模式》圖省略了 AnOperation(),切斷了模板方法與工廠方法的內在聯繫。
  3. 教學風險:讀者可能誤以為 Factory Method 就是「定義一個創建接口,子類實現,客戶端直接調用」,忽略了模板方法封裝不變流程這一核心價值。

正確的 Java 實現範例

// 框架層:定義不可變的文檔處理流程
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 頁,對照類圖與代碼,體會「繼承實現創建」與「委派實現創建」的深層差異。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved