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

Java 設計模式:簡單工廠模式深度解析與兩種實作方式對比

     編輯:Java 相關知識

前言

簡單工廠模式(Simple Factory Pattern)雖非 GoF 23 種經典設計模式之一,但作為工廠模式家族的入門基礎,廣泛應用於業務開發中。本文將通過「人類創建」案例,深度解析其結構、兩種實作方式(邏輯判斷 vs 反射)、優缺點與適用場景。

模式定義與 UML 結構

核心角色:

  • Factory(工廠類):包含創建邏輯,根據參數返回具體產品實例
  • Product(抽象產品):定義產品公共接口(如 Human)
  • ConcreteProduct(具體產品):實現抽象接口(如 Man、Woman)

UML 關係: Factory 依賴 Product,Client 僅依賴 Factory 與 Product,解耦具體實現類。

案例場景:人類工廠

1. 抽象產品接口

public interface Human {
    void say();
}

2. 具體產品實現

public class Man implements Human {
    @Override public void say() { System.out.println("男人"); }
}

public class Woman implements Human {
    @Override public void say() { System.out.println("女人"); }
}

實作方式一:邏輯判斷(硬編碼)

public class SimpleFactory {
    public static Human createHuman(String type) {
        if ("man".equalsIgnoreCase(type)) {
            return new Man();
        } else if ("woman".equalsIgnoreCase(type)) {
            return new Woman();
        } else {
            System.err.println("無法創建類型: " + type);
            return null;
        }
    }
}

特點: 直觀易懂,但違反開閉原則,新增類型需修改工廠代碼。

實作方式二:反射機制(動態加載)

public class SimpleFactoryReflect {
    public static Human createHuman(Class<? extends Human> clazz) {
        try {
            return clazz.getDeclaredConstructor().newInstance();
        } catch (InstantiationException e) {
            throw new IllegalArgumentException("不支援抽象類/介面: " + clazz);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("權限不足,無法訪問構造器: " + clazz);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("缺少無參構造器: " + clazz);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("構造器拋出異常: " + clazz, e.getCause());
        }
    }
}

優勢: 符合開閉原則,新增產品類無需修改工廠代碼;支援動態擴展(配置文件驅動)。

劣勢: 反射效能稍低(可緩存 Constructor)、丟失編譯期類型檢查、異常處理較繁瑣。

客戶端調用對比

public class Client {
    public static void main(String[] args) {
        // 方式一:字符串參數
        Human man1 = SimpleFactory.createHuman("man");
        man1?.say();

        // 方式二:Class 參數(推薦)
        Human man2 = SimpleFactoryReflect.createHuman(Man.class);
        Human woman2 = SimpleFactoryReflect.createHuman(Woman.class);
        man2.say(); woman2.say();
    }
}

優缺點深度分析

維度優點缺點
職責分離客戶端脫離具體創建邏輯,專注業務工廠類集中所有創建邏輯,違反高內聚
擴展性反射版本支援無侵入式擴展邏輯判斷版本需修改工廠源碼
維護性創建邏輯集中,易於統一管理產品類增多時工廠膨脹,條件分支複雜
效能邏輯判斷極快反射有額外開銷(可緩存優化)
類型安全邏輯判斷編譯期可檢查反射運行期才發現錯誤

適用場景與最佳實踐

✅ 適合使用場景

  • 產品類數量較少且相對固定(如:支付渠道、日誌輸出格式、報表導出類型)
  • 客戶端不關心具體創建細節,只需「拿到可用對象」
  • 配置驅動型系統:從配置文件讀取類名,反射實例化

❌ 不適合場景

  • 產品族複雜、層級多 → 改用工廠方法模式或抽象工廠模式
  • 高頻調用且極度敏感效能 → 考慮對象池或單例緩存
  • 需要編譯期強類型保證 → 直接 new 或依賴注入

進階優化:緩存 Constructor 提升反射效能

public class OptimizedFactory {
    private static final Map<Class<?>, Constructor<?>> CONSTRUCTOR_CACHE = new ConcurrentHashMap<>();

    @SuppressWarnings("unchecked")
    public static <T> T createInstance(Class<T> clazz) {
        Constructor<?> constructor = CONSTRUCTOR_CACHE.computeIfAbsent(clazz, c -> {
            try { return c.getDeclaredConstructor(); }
            catch (NoSuchMethodException e) { throw new IllegalArgumentException(e); }
        });
        try {
            constructor.setAccessible(true);
            return (T) constructor.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("實例化失敗: " + clazz, e);
        }
    }
}

總結

簡單工廠是「封裝變化」思想的入門實踐。邏輯判斷版適合簡單固定場景,反射版適合可擴展系統。實際開發中,Spring 的 BeanFactory、ApplicationContext 本質上是功能強大的工廠容器,掌握簡單工廠原理有助於深度理解 IOC 容器設計哲學。建議:簡單場景直寫邏輯,複雜場景交給 Spring 管理,避免過度設計。

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