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

Java 抽象工廠模式全解析:多產品族協同建立的架構藝術與實戰變體

     編輯:Java 相關知識

抽象工廠模式是工廠家族中最抽象、最具廣泛性的形態。它解決的核心問題是:系統需要建立多個相互關聯、相互依賴的產品族,且客戶端不應依賴具體產品的建立細節。本文系統講解抽象工廠的三維結構定義、適用場景判斷、小花果園雙園區案例、微型電腦生產系統案例,並深度剖析單例工廠、原型模式協作、動態工廠方法等進階實現變體。

一、抽象工廠 vs 工廠方法:維度躍升

位圖對比

  • 簡單工廠:一維(產品類型)
  • 工廠方法:二維(工廠類型 × 產品類型)
  • 抽象工廠:三維(工廠類型 × 產品類型 × 產品族)

抽象工廠三維位圖

關鍵洞察:當產品族維度 = 1時,第三維坍縮,抽象工廠退化為工廠方法。

二、適用場景:四大判斷條件

  1. 系統不應依賴產品建立、組合、表示細節(所有工廠模式共同前提)
  2. 系統有多於一個產品族(核心條件)
  3. 同一產品族的產品設計為協同使用(核心條件——北方園區植物一起種,南方園區植物一起種)
  4. 產品以介面形式出現,隱藏實現細節

三、案例一:小花果園雙園區系統

場景

  • 北方園區(溫帶):種植北方蔬菜 + 北方水果
  • 南方園區(亞熱帶):種植熱帶蔬菜 + 熱帶水果
  • 兩個園區 = 兩個產品族
  • 每族包含兩類產品:蔬菜、水果

UML 結構

抽象工廠應用於小花果園

核心代碼


// 抽象工廠介面
public interface Gardener {
    VeggieIF createVeggie(String name);
    FruitIF createFruit(String name);
}

// 北方具體工廠
public class NorthernGardener implements Gardener {
    public VeggieIF createVeggie(String name) { return new NorthernVeggie(name); }
    public FruitIF createFruit(String name) { return new NorthernFruit(name); }
}

// 南方具體工廠
public class TropicalGardener implements Gardener {
    public VeggieIF createVeggie(String name) { return new TropicalVeggie(name); }
    public FruitIF createFruit(String name) { return new TropicalFruit(name); }
}

// 抽象產品介面
public interface VeggieIF {}
public interface FruitIF {}

// 具體產品(簡化屬性)
public class NorthernVeggie implements VeggieIF { private String name; ... }
public class TropicalVeggie implements VeggieIF { private String name; ... }
// NorthernFruit, TropicalFruit 類似...

客戶端使用


Gardener gardener = isNorthern ? new NorthernGardener() : new TropicalGardener();
VeggieIF veggie = gardener.createVeggie("cabbage");
FruitIF fruit = gardener.createFruit("apple");
// 客戶端完全不依賴具體產品類

四、案例二:微型電腦生產系統(PC vs Mac)

微型電腦生產系統

  • 兩個產品族:PC 族、Mac 族
  • 每族包含:CPU、RAM、主機板、硬碟...
  • PC 族產品協同工作,Mac 族產品協同工作,跨族產品不可混用

五、進階實現變體與技巧

1. 具體工廠設計為單例

系統通常只需一個 NorthernGardener、一個 TropicalGardener 實例。


public class NorthernGardener implements Gardener {
    private static final NorthernGardener INSTANCE = new NorthernGardener();
    private NorthernGardener() {}
    public static NorthernGardener getInstance() { return INSTANCE; }
    // ... 工廠方法
}

參考:單例模式三大實現

2. 引入原型模式減少重複代碼

問題:多個具體工廠結構高度相似(皆有 createCPU、createRAM...)。
解決:使用原型模式克隆基礎工廠,再微調差異部分。

3. 扁平化工廠方法:createPart(String type)

問題:新增產品類型(如硬碟)需修改介面、所有工廠類、所有產品類。
方案:合併為單一方法:


public interface ComputerFactory {
    Part createPart(String type); // type: "CPU", "RAM", "HD"
}

public interface Part {
    String getType(); // 返回 "CPU"/"RAM"/"HD"
}

代價:型別安全性降低,客戶端拿到的永遠是 Part 介面,需自行轉型檢查。

4. 抽象工廠配備靜態工廠方法

方案 A:單一方法按參數返回具體工廠


public abstract class ComputerFactory {
    public static ComputerFactory getFactory(String which) {
        if (which.equalsIgnoreCase("PC")) return new PCFactory();
        else if (which.equalsIgnoreCase("Mac")) return new MacFactory();
        throw new IllegalArgumentException();
    }
}

方案 B:每個具體工廠對應一個靜態方法


public abstract class ComputerFactory {
    public static PCFactory getPCFactory() { return PCFactory.getInstance(); }
    public static MacFactory getMacFactory() { return MacFactory.getInstance(); }
}

六、練習題參考答案

練習 1:抽象工廠改為抽象類 + 靜態 getProducer(String)

練習1類圖


public abstract class ComputerProducer {
    public static ComputerProducer getProducer(String which) {
        if (which.equalsIgnoreCase("PC")) return new PCProducer();
        else if (which.equalsIgnoreCase("Mac")) return new MacProducer();
        throw new IllegalArgumentException();
    }
    public abstract CPU createCPU();
    public abstract RAM createRAM();
}

練習 3:具體工廠改為單例(餓漢式)

練習3類圖


public abstract class ComputerProducer {
    public static ComputerProducer getProducer(String which) {
        if (which.equalsIgnoreCase("PC")) return PCProducer.getInstance();
        else if (which.equalsIgnoreCase("Mac")) return MacProducer.getInstance();
        throw new IllegalArgumentException();
    }
}

public class PCProducer extends ComputerProducer {
    private PCProducer() {}
    private static final PCProducer INSTANCE = new PCProducer();
    public static PCProducer getInstance() { return INSTANCE; }
    public CPU createCPU() { return new PCCPU(); }
    public RAM createRAM() { return new PCRAM(); }
}
// MacProducer 類似...

七、總結:工廠三部曲選型指南

模式核心結構適用場景擴展方式
簡單工廠單一具體工廠類 + if-else單一產品族、類型固定、變化少修改工廠類(違反 OCP)
工廠方法抽象工廠 + 多個具體工廠子類多產品族、單維度產品變化新增具體工廠子類(符合 OCP)
抽象工廠抽象工廠 + 多具體工廠 + 多產品族介面多產品族、族內產品強協同、跨族不可混用新增具體工廠 + 全族產品(符合 OCP)

架構師心法:不要為了用模式而用模式。從簡單工廠開始,當產品維度增加、變化頻率上升、跨族協同約束出現時,自然演進至工廠方法、抽象工廠。模式是對變化維度的回應,而非代碼裝飾品。

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