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

Java 工廠模式深度解析:簡單工廠、工廠方法、抽象工廠三層進化與實戰選型指南

     編輯:Java 綜合教學

前言

工廠模式是創建型模式基石,核心目的是封裝對象創建邏輯、解耦調用者與具體實現類。本文從最基礎的簡單工廠講起,層層遞進至工廠方法、抽象工廠,並給出 Spring 源碼級應用場景、選型決策樹與最佳實踐。

一、核心角色統一術語

  • Product (產品): 定義產品接口 (Shape)
  • ConcreteProduct (具體產品): 實現接口 (Circle, Rectangle)
  • Factory (工廠): 創建產品的接口/類
  • Client (客戶端): 僅依賴產品接口與工廠接口

二、第一層:簡單工廠 (Simple Factory) — 非標準模式但極實用

定義

一個類根據傳入參數決定創建哪種產品實例。違反開閉原則 (新增產品需修改工廠代碼),但結構簡單,適用於產品類型固定、創建邏輯不複雜場景。

代碼實現

// 1. 產品接口
public interface Shape {
    void draw();
    double area();
}

// 2. 具體產品
public class Circle implements Shape {
    private final double radius;
    public Circle(double radius) { this.radius = radius; }
    @Override public void draw() { System.out.println("繪製圓形 r=" + radius); }
    @Override public double area() { return Math.PI * radius * radius; }
}

public class Rectangle implements Shape {
    private final double width, height;
    public Rectangle(double w, double h) { this.width = w; this.height = h; }
    @Override public void draw() { System.out.println("繪製矩形 " + width + "x" + height); }
    @Override public double area() { return width * height; }
}

public class Square implements Shape {
    private final double side;
    public Square(double side) { this.side = side; }
    @Override public void draw() { System.out.println("繪製正方形 " + side); }
    @Override public double area() { return side * side; }
}

// 3. 簡單工廠 (靜態方法版)
public final class ShapeFactory {
    private ShapeFactory() {} // 防止實例化
    
    public static Shape createShape(String type, double... params) {
        return switch (type.toLowerCase()) {
            case "circle" -> new Circle(params[0]);
            case "rectangle" -> new Rectangle(params[0], params[1]);
            case "square" -> new Square(params[0]);
            default -> throw new IllegalArgumentException("未知形狀: " + type);
        };
    }
}

// 4. 客戶端調用
public class Client {
    public static void main(String[] args) {
        Shape c = ShapeFactory.createShape("circle", 5.0);
        c.draw(); // 繪製圓形 r=5.0
        System.out.println("面積: " + c.area());
    }
}

三、第二層:工廠方法模式 (Factory Method) — 開閉原則的守護者

定義

定義創建對象的接口,由子類決定實例化哪個具體類。將創建責任下放到子類,新增產品只需新增工廠子類,**不修改現有代碼**。

結構

// 1. 抽象工廠接口
public interface ShapeFactory {
    Shape createShape(double... params);
}

// 2. 具體工廠 (每種產品一個工廠類)
public class CircleFactory implements ShapeFactory {
    @Override public Shape createShape(double... params) {
        return new Circle(params[0]);
    }
}

public class RectangleFactory implements ShapeFactory {
    @Override public Shape createShape(double... params) {
        return new Rectangle(params[0], params[1]);
    }
}

// 3. 客戶端依賴抽象工廠
public class DrawingApp {
    private final ShapeFactory factory;
    public DrawingApp(ShapeFactory factory) { this.factory = factory; }
    
    public void drawShape(double... params) {
        Shape shape = factory.createShape(params);
        shape.draw();
    }
}

// 4. 使用 (可配合 DI 容器注入具體工廠)
public class Main {
    public static void main(String[] args) {
        DrawingApp app = new DrawingApp(new CircleFactory());
        app.drawShape(10.0);
    }
}

Spring 中的經典應用

// FactoryBean 接口:Spring 內建工廠方法模式
public interface FactoryBean<T> {
    T getObject() throws Exception;
    Class<?> getObjectType();
    boolean isSingleton();
}

// 典型實現:SqlSessionFactoryBean (MyBatis)、LocalContainerEntityManagerFactoryBean (JPA)
// 客戶端注入 SqlSessionFactory,完全感知不到創建邏輯

四、第三層:抽象工廠模式 (Abstract Factory) — 產品族創建

定義

提供一個接口,用於創建相關或依賴對象的家族,而無需指定具體類。適用於系統有多個產品族、客戶端只使用某一族產品的場景。

經典案例:跨平台 GUI 組件族

// 1. 產品族接口
public interface Button { void render(); void onClick(Runnable action); }
public interface Checkbox { void render(); void toggle(); }
public interface ScrollBar { void render(); }

// 2. Windows 族具體產品
public class WindowsButton implements Button { /* ... */ }
public class WindowsCheckbox implements Checkbox { /* ... */ }
public class WindowsScrollBar implements ScrollBar { /* ... */ }

// 3. Mac 族具體產品
public class MacButton implements Button { /* ... */ }
public class MacCheckbox implements Checkbox { /* ... */ }
public class MacScrollBar implements ScrollBar { /* ... */ }

// 4. 抽象工廠:定義創建整族產品的方法群
public interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
    ScrollBar createScrollBar();
}

// 5. 具體工廠:每族一個
public class WindowsFactory implements GUIFactory {
    @Override public Button createButton() { return new WindowsButton(); }
    @Override public Checkbox createCheckbox() { return new WindowsCheckbox(); }
    @Override public ScrollBar createScrollBar() { return new WindowsScrollBar(); }
}

public class MacFactory implements GUIFactory {
    @Override public Button createButton() { return new MacButton(); }
    @Override public Checkbox createCheckbox() { return new MacCheckbox(); }
    @Override public ScrollBar createScrollBar() { return new MacScrollBar(); }
}

// 6. 客戶端:僅依賴抽象工廠與產品接口
public class Application {
    private final Button button;
    private final Checkbox checkbox;
    
    public Application(GUIFactory factory) {
        button = factory.createButton();
        checkbox = factory.createCheckbox();
    }
    
    public void renderUI() {
        button.render();
        checkbox.render();
    }
}

// 7. 運行時動態切換族
public class Main {
    public static void main(String[] args) {
        String os = System.getProperty("os.name").toLowerCase();
        GUIFactory factory = os.contains("mac") ? new MacFactory() : new WindowsFactory();
        new Application(factory).renderUI();
    }
}

五、三大模式對比決策樹

維度簡單工廠工廠方法抽象工廠
創建責任集中在一個類分散到多個子類分散到多個工廠實現
產品結構單一產品等級單一產品等級多產品族 (多等級)
擴展新產品修改工廠類 (違反 OCP)新增工廠子類 (符合 OCP)新增工廠實現+全族產品
擴展新產品族不支持不支持新增工廠實現 (符合 OCP)
客戶端依賴具體工廠類抽象工廠接口抽象工廠接口
典型場景工具類、參數化創建、產品固定少框架擴展點、插件系統、單產品多實現跨平台、多主題、多數據源適配器
複雜度低中高

六、現代 Java 最佳實踐

1. 函數式工廠 (Java 8+)

 new Circle(p[0]));
        REGISTRY.put("rectangle", p -> new Rectangle(p[0], p[1]));
    }
    public static Shape create(String type, double... params) {
        return REGISTRY.getOrDefault(type, p -> { throw new IllegalArgumentException(); }).apply(params);
    }
    // 支持運行時動態註冊:REGISTRY.put("triangle", p -> new Triangle(...));
}

2. 服務加載機制 (SPI) 實現插件化工廠方法

// META-INF/services/com.example.ShapeFactory
# 實現類全限定名
com.example.CircleFactory
com.example.RectangleFactory

// 運行時發現所有實現
ServiceLoader<ShapeFactory> loader = ServiceLoader.load(ShapeFactory.class);
for (ShapeFactory f : loader) {
    // 自動發現第三方 JAR 提供的工廠
}

3. Spring @Conditional 動態裝配工廠

@Configuration
public class FactoryConfig {
    @Bean @ConditionalOnProperty(name = "shape.type", havingValue = "circle")
    public ShapeFactory circleFactory() { return new CircleFactory(); }
    
    @Bean @ConditionalOnProperty(name = "shape.type", havingValue = "rectangle")
    public ShapeFactory rectangleFactory() { return new RectangleFactory(); }
}

七、避坑指南

  1. 過度設計: 產品類型固定、創建邏輯簡單時,直接 `new` 或簡單工廠足矣,勿強行上工廠方法/抽象工廠。
  2. 工廠爆炸: 工廠方法每個產品一個工廠類,產品多時類數量膨脹。考慮參數化工廠或註冊表模式。
  3. 違反單一職責: 工廠類承擔過多創建邏輯 (解析配置、依賴注入、生命周期管理)。拆分為 Builder/Factory/Provider 協作。
  4. 忽略緩存/池化: 昂貴對象 (連接池、線程池、大對象) 工廠需內建單例/池化邏輯,而非每次新建。

結語

工廠模式三層進化本質是創建邏輯封裝層級的提升:簡單工廠封裝「判斷邏輯」,工廠方法封裝「創建類決策」,抽象工廠封裝「產品族一致性」。實戰中遵循「簡單優先、按需演進、接口隔離、註冊表替代繼承」原則,配合現代 Java 函數式特性與 SPI 機制,能構建出既靈活又可維護的對象創建體系。

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