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

工廠模式全解析:簡單工廠、工廠方法與抽象工廠的演進與實戰

     編輯:Java 綜合教學

工廠模式全解析:簡單工廠、工廠方法與抽象工廠的演進與實戰

核心目的:解耦物件創建與使用

工廠模式屬於創建型模式,核心思想是將物件實例化邏輯封裝在工廠中,客戶端僅依賴抽象介面(介面或抽象類),不依賴具體實現類,實現「開閉原則」——對擴展開放,對修改關閉。

三大工廠模式演進關係圖

簡單工廠(靜態工廠方法)
    │
    ├─ 問題:違反開閉原則,新增產品需修改工廠類
    │
    ▼
工廠方法(多態工廠)
    │
    ├─ 解決:每個產品對應一個具體工廠,新增產品只需新增工廠類
    ├─ 問題:類別爆炸,單一產品族場景下過度設計
    │
    ▼
抽象工廠(產品族工廠)
    │
    └─ 解決:一個工廠創建多個相關/依賴的產品族,約束產品間一致性

一、簡單工廠模式

結構角色

  • 抽象產品:定義產品介面(Fruit)
  • 具體產品:實作介面(Apple、Grape)
  • 工廠類:靜態方法根據參數決定創建哪個產品(FruitFactory)

程式碼實作

// 抽象產品
public interface Fruit {
    void fruitType();
}

// 具體產品
public class Apple implements Fruit {
    public void fruitType() { System.out.println("這是蘋果"); }
}
public class Grape implements Fruit {
    public void fruitType() { System.out.println("這是葡萄"); }
}

// 簡單工廠
public class FruitFactory {
    public static Fruit createFruit(String type) {
        if ("apple".equalsIgnoreCase(type)) return new Apple();
        if ("grape".equalsIgnoreCase(type)) return new Grape();
        throw new IllegalArgumentException("未知水果類型: " + type);
    }
}

// 客戶端
Fruit fruit = FruitFactory.createFruit("apple");
fruit.fruitType();

優缺點評析

優點缺點
客戶端與具體類解耦工廠類集中所有創建邏輯,違反單一職責
簡單易懂、易實作新增產品必須修改工廠原始碼(違反開閉原則)
靜態方法調用方便難以擴展、測試困難(靜態方法難 Mock)

二、工廠方法模式

結構角色

  • 抽象工廠:宣告工廠方法(Factory 介面)
  • 具體工廠:實作工廠方法,創建對應產品(AppleFactory、GrapeFactory)
  • 抽象產品/具體產品:同簡單工廠

程式碼實作

// 工廠介面
public interface Factory {
    Fruit createFruit();
}

// 具體工廠:一個工廠對應一個產品
public class AppleFactory implements Factory {
    public Fruit createFruit() { return new Apple(); }
}
public class GrapeFactory implements Factory {
    public Fruit createFruit() { return new Grape(); }
}

// 客戶端:依賴抽象工廠
public class FruitStore {
    private final Factory factory;
    public FruitStore(Factory factory) { this.factory = factory; }
    public Fruit sellFruit() { return factory.createFruit(); }
}

// 使用
FruitStore appleStore = new FruitStore(new AppleFactory());
Fruit apple = appleStore.sellFruit();

優缺點評析

優點缺點
符合開閉原則,新增產品只需新增工廠類類別數量成倍增加(每個產品一個工廠)
支援多態,便於測試與替換單一產品族場景下過度設計
客戶端完全面向介面程式設計若產品層級固定,不如簡單工廠實用

三、抽象工廠模式

核心概念:產品族

當系統有多個產品等級結構(如:水果種類蘋果/葡萄 × 水果等級普通/優質/有機),且需要約束特定組合(如:有機蘋果只能搭配有機包裝),抽象工廠提供統一介面創建一族相關產品。

結構角色

  • 抽象工廠:宣告多個工廠方法,每個方法創建一種產品(Factory1)
  • 具體工廠:實作所有方法,創建特定族群的所有產品(AppleFactory1 創建 Apple1、Apple2)
  • 抽象產品:每個等級一個介面(Fruit、Package)
  • 具體產品:各族群的具體實作

程式碼實作

// 多個抽象產品
public interface Fruit { void fruitType(); }
public interface Package { void pack(); }

// 抽象工廠:定義創建一族產品的方法
public interface AbstractFactory {
    Fruit createFruit();
    Package createPackage();
}

// 具體工廠:有機水果族
public class OrganicFactory implements AbstractFactory {
    public Fruit createFruit() { return new OrganicApple(); }
    public Package createPackage() { return new OrganicPackage(); }
}

// 具體工廠:普通水果族
public class NormalFactory implements AbstractFactory {
    public Fruit createFruit() { return new NormalApple(); }
    public Package createPackage() { return new NormalPackage(); }
}

// 客戶端
public class FruitShop {
    private final AbstractFactory factory;
    public FruitShop(AbstractFactory factory) { this.factory = factory; }
    public void sellSet() {
        Fruit fruit = factory.createFruit();
        Package pkg = factory.createPackage();
        fruit.fruitType();
        pkg.pack();
    }
}

優缺點評析

優點缺點
約束產品族內部一致性(有機配有機)新增產品等級(如加入 Juice)需修改所有工廠介面與實作
客戶端與具體產品完全解耦複雜度高,簡單場景殺雞用牛刀
易於切換整個產品族(季節換裝)類別爆炸嚴重

四、模式選型決策指南

場景分析:
├─ 單一產品等級、產品數量固定/極少變動 → 簡單工廠(或直接 new)
├─ 單一產品等級、頻繁新增產品、需多態替換 → 工廠方法
├─ 多個產品等級、存在產品族約束、需整體切換 → 抽象工廠
└─ 極簡場景、無擴展需求 → 直接 new / 依賴注入框架管理

五、實戰最佳實踐與現代演進

1. 結合依賴注入(Spring/CDI)

現代框架下,工廠多由容器管理,@Bean 方法即為工廠方法,@Configuration 類即為抽象工廠。

2. 參數化工廠方法

// 靈活參數化,減少工廠類數量
public interface FruitFactory {
    Fruit createFruit(String variety, Grade grade);
}

3. 登記式工廠

// 執行時動態註冊,支援外掛擴展
public class FruitRegistry {
    private static final Map> REGISTRY = new ConcurrentHashMap<>();
    public static void register(String key, Supplier supplier) {
        REGISTRY.put(key, supplier);
    }
    public static Fruit create(String key) {
        Supplier s = REGISTRY.get(key);
        if (s == null) throw new IllegalArgumentException("Unknown: " + key);
        return s.get();
    }
}

4. 函數式介面簡化

// Java 8+ 使用 Supplier/Function 替代工廠介面
Supplier appleSupplier = Apple::new;
Function fruitFactory = type -> "apple".equals(type) ? new Apple() : new Grape();

六、總結

三種工廠模式本質相同——封裝變化、解耦依賴。實務中不必拘泥於學術定義,根據業務變化率、產品結構複雜度、團隊熟悉度靈活選擇或組合。核心原則:**客戶端依賴抽象,具體創建邏輯集中管理,新增功能不修改既有代碼**。

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