設計模式——抽象工廠設計模式(創建型)

摘要

抽象工廠設計模式是一種創建型設計模式,旨在提供一個接口,用于創建一系列相關或依賴的對象,無需指定具體類。它通過抽象工廠、具體工廠、抽象產品和具體產品等組件構建,相比工廠方法模式,能創建一個產品族。該模式適用于多個產品需一起創建的場景,可隱藏產品細節,便于客戶端使用。

1. 抽象工廠設計模式定義

抽象工廠模式創建型設計模式的一種,它提供一個接口,用于創建一系列相關或相互依賴的對象,而無需指定它們的具體類。就像一個“超級工廠”,里面包含多個子工廠,用于生產同一產品族中的各種產品。你不關心產品的具體實現,只關心工廠能提供什么樣的系列產品。

核心要點:

維度

描述

意圖

為創建相關對象的家族提供一個統一的接口

解決問題

解決“多個產品之間需要一起創建”的問題

與工廠方法對比

工廠方法是一個產品一個工廠;抽象工廠是一個產品族一個工廠

隱藏細節

客戶端不需要知道具體產品類,只通過抽象接口使用

2. 抽象工廠設計模式結構

2.1. 抽象工廠設計模式類圖

  • AbstractFactory:抽象工廠
  • ConcreteFactory:具體工廠
  • AbstractProduct:抽象產品
  • Product:具體產品

2.2. 抽象工廠設計模式時序圖

3. 抽象工廠設計模式實現方式

抽象工廠模式的實現,主要通過一組產品接口 + 一個抽象工廠接口 + 多個具體工廠實現類來構建。下面是完整的標準實現方式。

3.1. 🧱 實現步驟(Java 示例)

3.1.1. 定義抽象產品接口

// 抽象產品 A
public interface Button {void click();
}// 抽象產品 B
public interface TextField {void input(String text);
}

3.1.2. 定義具體產品類

// Windows 系列產品
public class WindowsButton implements Button {public void click() {System.out.println("Windows 按鈕點擊");}
}public class WindowsTextField implements TextField {public void input(String text) {System.out.println("Windows 輸入: " + text);}
}// Mac 系列產品
public class MacButton implements Button {public void click() {System.out.println("Mac 按鈕點擊");}
}public class MacTextField implements TextField {public void input(String text) {System.out.println("Mac 輸入: " + text);}
}

3.1.3. 定義抽象工廠接口

public interface GUIFactory {Button createButton();TextField createTextField();
}

3.1.4. 實現具體工廠類

public class WindowsFactory implements GUIFactory {public Button createButton() {return new WindowsButton();}public TextField createTextField() {return new WindowsTextField();}
}public class MacFactory implements GUIFactory {public Button createButton() {return new MacButton();}public TextField createTextField() {return new MacTextField();}
}

3.1.5. 客戶端使用示例

public class Application {public static void main(String[] args) {// 可通過配置文件或環境變量來控制GUIFactory factory = new WindowsFactory();// GUIFactory factory = new MacFactory();Button button = factory.createButton();TextField textField = factory.createTextField();button.click();textField.input("Hello World!");}
}

3.2. ? 抽象工廠模式特點

特點

描述

解耦

客戶端不需要了解產品的具體類

易于擴展

可以輕松新增新的產品族,只需添加一個新的工廠類

成本

新增產品種類時,需要修改所有工廠類(違背開閉原則)

應用場景

多產品族、產品組合固定、創建邏輯復雜的場景

4. 抽象工廠設計模式適合場景

抽象工廠是一種創建型設計模式,適用于需要一組相關或互相依賴的對象的場景。

4.1. ? 適合使用抽象工廠模式的場景

場景

說明

產品族固定,且產品之間有依賴關系

比如 GUI 界面中,按鈕、文本框等控件需風格統一(如 Windows、Mac)。

系統需要獨立于產品創建邏輯

客戶端無需關心產品如何創建,只關注使用接口。

需要保證產品之間的一致性(風格/協議/行為)

比如同一品牌的組件應配套使用,避免混搭出錯。

系統有多個產品族,但每次只使用其中一個

比如數據庫連接池的不同廠商實現(Druid、HikariCP)。

適合用于“橫向擴展”產品族,而不是“縱向擴展”產品種類

可以增加新的平臺或風格,但不易增加產品接口。

4.2. ? 不適合使用抽象工廠模式的場景

場景

原因

? 只需要創建一種對象,不是一個產品族

比如只創建不同類型的日志對象,用簡單工廠或策略更合適。

? 頻繁增加新的產品(產品等級結構)

每新增一個產品類型(接口),所有具體工廠都要修改,違背“開閉原則”。

? 產品之間無依賴、不要求一致性

沒有必要引入抽象工廠,使用簡單工廠或直接實例化即可。

? 產品構造非常簡單,擴展性需求低

抽象工廠的結構較復雜,維護成本較高,可能得不償失。

? 僅用于單一系統或開發周期很短的小項目

引入抽象工廠會增加架構復雜度。

4.3. 📌 抽象工廠設計模式總結

項目

抽象工廠適用

不適用

是否一組產品族

? 是

? 否

是否要求統一風格

? 是

? 否

是否頻繁新增產品接口

? 否

? 是

是否希望屏蔽實例化邏輯

? 是

? 否

5. 抽象工廠設計模式實戰示例

在金融風控系統中,不同的業務線(如消費貸、車貸、現金貸等)往往使用不同的風控規則引擎或評分模型。抽象工廠模式在這里可以用于隔離不同業務線的策略實現,提升系統的可擴展性和解耦能力。

5.1. ? 多業務線風控規則工廠示例:

系統支持多個業務線,每個業務線都有自己的一套風控規則引擎(如用戶畫像評分、反欺詐規則、額度評估等),需要統一接口、按業務線隔離實現。

5.2. 🧱 抽象設計結構

  • 抽象產品:RiskRuleEngine(風控規則引擎)
  • 抽象工廠:RiskRuleFactory(風控規則工廠)
  • 具體工廠:ConsumerLoanFactoryCarLoanFactory
  • 客戶端:風控服務,根據業務類型獲取對應工廠并執行規則引擎

5.3. 🧩 代碼結構

5.3.1. 抽象產品接口

public interface RiskRuleEngine {void evaluate(String userId);
}

5.3.2. 抽象工廠接口

public interface RiskRuleFactory {RiskRuleEngine createUserProfileEngine();RiskRuleEngine createFraudEngine();RiskRuleEngine createCreditLimitEngine();
}

5.3.3. 具體產品實現(以消費貸為例)

@Component
public class ConsumerUserProfileEngine implements RiskRuleEngine {public void evaluate(String userId) {System.out.println("消費貸 - 用戶畫像評估:" + userId);}
}@Component
public class ConsumerFraudEngine implements RiskRuleEngine {public void evaluate(String userId) {System.out.println("消費貸 - 反欺詐規則評估:" + userId);}
}@Component
public class ConsumerCreditLimitEngine implements RiskRuleEngine {public void evaluate(String userId) {System.out.println("消費貸 - 授信額度評估:" + userId);}
}

5.3.4. 消費貸工廠實現

@Component("consumerLoanFactory")
public class ConsumerLoanFactory implements RiskRuleFactory {@Autowired private ConsumerUserProfileEngine userProfileEngine;@Autowired private ConsumerFraudEngine fraudEngine;@Autowired private ConsumerCreditLimitEngine creditLimitEngine;public RiskRuleEngine createUserProfileEngine() {return userProfileEngine;}public RiskRuleEngine createFraudEngine() {return fraudEngine;}public RiskRuleEngine createCreditLimitEngine() {return creditLimitEngine;}
}

5.3.5. 客戶端服務按業務線執行風控評估

@Service
public class RiskControlService {@Autowired@Qualifier("consumerLoanFactory") // 或通過配置中心動態選擇工廠private RiskRuleFactory riskRuleFactory;public void doRiskEvaluate(String userId) {riskRuleFactory.createUserProfileEngine().evaluate(userId);riskRuleFactory.createFraudEngine().evaluate(userId);riskRuleFactory.createCreditLimitEngine().evaluate(userId);}
}

5.4. ? 如果要支持動態業務線切換(如配置中心配置當前業務)

你可以將所有工廠注冊進一個 Map:

@Component
public class RiskRuleFactoryRegistry {private final Map<String, RiskRuleFactory> factoryMap = new HashMap<>();@Autowiredpublic RiskRuleFactoryRegistry(List<RiskRuleFactory> factories) {for (RiskRuleFactory factory : factories) {factoryMap.put(factory.getClass().getSimpleName().replace("Factory", "").toLowerCase(), factory);}}public RiskRuleFactory getFactory(String bizType) {return factoryMap.get(bizType.toLowerCase());}
}

5.5. ? 使用配置中心動態切換工廠

@Service
public class DynamicRiskControlService {@Value("${biz.line.type:consumerLoan}")private String bizType;@Autowiredprivate RiskRuleFactoryRegistry registry;public void doEvaluate(String userId) {RiskRuleFactory factory = registry.getFactory(bizType);factory.createUserProfileEngine().evaluate(userId);factory.createFraudEngine().evaluate(userId);factory.createCreditLimitEngine().evaluate(userId);}
}

5.6. ? 抽象工廠涉及面模式總結

優勢

描述

模塊隔離

不同業務線的規則邏輯完全隔離,避免混亂

易于擴展

新業務線只需實現一套工廠和引擎,不影響老業務

支持插件化

工廠可結合 SPI 動態加載

配置驅動

支持配置中心動態切換業務邏輯

6. 抽象工廠設計模式思考

6.1. 引入SPI 加載抽象工廠、或者結合 Spring Boot Starter 自動注冊不同業務線的風控策略示例

6.1.1. 需求回顧

  • 多業務線(消費貸、車貸等)各自實現一套 RiskRuleFactory
  • 通過 SPI 機制實現工廠插件化,支持 jar 擴展、熱插拔。
  • Spring Boot 啟動時自動掃描 SPI 實現,注冊到工廠注冊中心。
  • 支持根據配置動態切換當前業務線風控工廠。

6.1.2. 項目結構示例

risk-control-spi/├─ META-INF/services/com.example.risk.spi.RiskRuleFactory├─ com/example/risk/spi/│    ├─ RiskRuleFactory.java       // SPI接口│    ├─ ConsumerLoanFactory.java   // 業務線1實現│    ├─ CarLoanFactory.java        // 業務線2實現├─ com/example/risk/spring/│    ├─ RiskRuleFactoryRegistry.java│    ├─ RiskControlAutoConfiguration.java│    ├─ DynamicRiskControlService.java

6.1.3. 示例代碼

SPI接口定義(RiskRuleFactory

package com.example.risk.spi;public interface RiskRuleFactory {// 返回業務線標識,如 "consumerLoan"String getBizType(); void evaluateUserProfile(String userId);void evaluateFraud(String userId);void evaluateCreditLimit(String userId);
}

SPI實現(以消費貸為例)

package com.example.risk.spi;public class ConsumerLoanFactory implements RiskRuleFactory {@Overridepublic String getBizType() {return "consumerLoan";}@Overridepublic void evaluateUserProfile(String userId) {System.out.println("消費貸用戶畫像評估: " + userId);}@Overridepublic void evaluateFraud(String userId) {System.out.println("消費貸反欺詐評估: " + userId);}@Overridepublic void evaluateCreditLimit(String userId) {System.out.println("消費貸授信額度評估: " + userId);}
}

同理實現 CarLoanFactory 等其他業務線工廠。

SPI配置文件:文件路徑:src/main/resources/META-INF/services/com.example.risk.spi.RiskRuleFactory內容(每行一個實現類全限定名):

com.example.risk.spi.ConsumerLoanFactory
com.example.risk.spi.CarLoanFactory

工廠注冊中心(Spring Bean)

package com.example.risk.spring;import com.example.risk.spi.RiskRuleFactory;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.util.*;@Component
public class RiskRuleFactoryRegistry {private final Map<String, RiskRuleFactory> factoryMap = new HashMap<>();@PostConstructpublic void init() {ServiceLoader<RiskRuleFactory> loader = ServiceLoader.load(RiskRuleFactory.class);for (RiskRuleFactory factory : loader) {factoryMap.put(factory.getBizType(), factory);System.out.println("加載風控工廠:" + factory.getBizType());}}public RiskRuleFactory getFactory(String bizType) {RiskRuleFactory factory = factoryMap.get(bizType);if (factory == null) {throw new IllegalArgumentException("不支持的業務線: " + bizType);}return factory;}
}

Spring Boot 自動配置類

package com.example.risk.spring;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConditionalOnProperty(prefix = "risk.control", name = "enabled", havingValue = "true", matchIfMissing = true)
public class RiskControlAutoConfiguration {@Beanpublic RiskRuleFactoryRegistry riskRuleFactoryRegistry() {return new RiskRuleFactoryRegistry();}@Beanpublic DynamicRiskControlService dynamicRiskControlService() {return new DynamicRiskControlService();}
}

動態風控服務

package com.example.risk.spring;import com.example.risk.spi.RiskRuleFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;@Service
public class DynamicRiskControlService {@Value("${risk.control.bizType:consumerLoan}")private String bizType;@Autowiredprivate RiskRuleFactoryRegistry registry;public void doEvaluate(String userId) {RiskRuleFactory factory = registry.getFactory(bizType);factory.evaluateUserProfile(userId);factory.evaluateFraud(userId);factory.evaluateCreditLimit(userId);}
}

6.1.4. SPI+抽象工廠設計模式總結

  1. 擴展業務線:只需實現 RiskRuleFactory 接口,并在 SPI 文件里聲明實現類,打包成 jar 加入項目。
  2. 動態切換業務線:修改配置 risk.control.bizType=carLoan 即可切換到車貸業務線風控。
  3. 熱插拔:新的業務線可以單獨打包成 jar 通過 SPI 機制自動被加載。

優點

說明

插件式擴展

新增業務線無需改動核心代碼,符合開閉原則

Spring 集成

自動裝配,減少手動配置

配置驅動

通過配置靈活切換業務邏輯

動態加載

SPI 支持運行時加載多個實現

博文參考

  • 3. 抽象工廠模式(Abstract Factory) — Graphic Design Patterns
  • 抽象工廠設計模式
  • 創建型 - 抽象工廠(Abstract Factory) | Java 全棧知識體系

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85622.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85622.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85622.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Express教程【006】:使用Express寫接口

文章目錄 8、使用Express寫接口8.1 創建API路由模塊8.2 編寫GET接口8.3 編寫POST接口 8、使用Express寫接口 8.1 創建API路由模塊 1??新建routes/apiRouter.js路由模塊&#xff1a; /*** 路由模塊*/ // 1-導入express const express require(express); // 2-創建路由對象…

【iOS(swift)筆記-14】App版本不升級時本地數據庫sqlite更新邏輯二

App版本不升級時&#xff0c;又想即時更新本地數據庫怎么辦&#xff1f; 辦法二&#xff1a;從服務器下載最新的sqlite數據替換掉本地的數據&#xff08;注意是數據不是文件&#xff09; 稍加調整&#xff0c; // &#xff01;&#xff01;&#xff01;注意&#xff01;&…

Mac電腦_鑰匙串操作選項變灰的情況下如何刪除?

Mac電腦_鑰匙串操作選項變灰的情況下如何刪除&#xff1f; 這時候 可以使用相關的終端命令進行操作。 下面附加文章《Mac電腦_鑰匙串操作的終端命令》。 《Mac電腦_鑰匙串操作的終端命令》 &#xff08;來源&#xff1a;百度~百度AI 發布時間&#xff1a;2025-06&#xff09;…

對接系統外部服務組件技術方案

概述 當前系統需與多個外部系統對接,然而外部系統穩定性存在不確定性。對接過程中若出現異常,需依靠雙方的日志信息來定位問題,但若日志信息不夠完整,會極大降低問題定位效率。此外,問題發生后,很大程度上依賴第三方的重試機制,若第三方缺乏完善的重試機制,就需要手動…

WAF繞過,網絡層面后門分析,Windows/linux/數據庫提權實驗

一、WAF繞過文件上傳漏洞 win7&#xff1a;10.0.0.168 思路&#xff1a;要想要繞過WAF&#xff0c;第一步是要根據上傳的內容找出來被攔截的原因。對于文件上傳有三個可以考慮的點&#xff1a;文件后綴名&#xff0c;文件內容&#xff0c;文件類型。 第二步是根據找出來的攔截原…

一文學會c++中的內存管理知識點

文章目錄 c/c內存管理c語言動態內存管理c動態內存管理new/delete自定義類型妙用operator new和operator delete malloc/new&#xff0c;free/delete區別 c/c內存管理 int globalVar 1;static int staticGlobalVar 1;void Test(){static int staticVar 1;int localVar 1;in…

深入解析Linux死鎖:原理、原因及解決方案

Linux死鎖是系統資源管理的致命陷阱&#xff0c;平均每年導致全球數據中心約??3.7億小時??的服務中斷。本文深度剖析死鎖形成的??四個必要條件??和六種典型死鎖場景&#xff0c;結合Linux內核源碼層級的資源管理機制&#xff0c;揭示文件系統鎖、內存分配、多線程同步等…

SKUA-GOCAD入門教程-第八節 線的創建與編輯2

8.1.3根據線創建曲線 (1)從線生成線 這個命令可以將一組曲線合并為一條曲線。每個輸入曲線都會成為新曲線內的一個部分。 1、選擇 Curve commands > New > Curves 打開對話框。 圖1 根據曲線創建曲線 在“name”框中

『uniapp』把接口的內容下載為txt本地保存 / 讀取本地保存的txt文件內容(詳細圖文注釋)

目錄 預覽效果思路分析downloadTxt 方法readTxt 方法 完整代碼總結 歡迎關注 『uniapp』 專欄&#xff0c;持續更新中 歡迎關注 『uniapp』 專欄&#xff0c;持續更新中 預覽效果 思路分析 downloadTxt 方法 該方法主要完成兩個任務&#xff1a; 下載 txt 文件&#xff1a;通…

攻防世界-unseping

進入環境 在獲得的場景中發現PHP代碼并進行分析 編寫PHP編碼 得到 Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czozOiJwd2QiO319 將其傳入 想執行ls&#xff0c;但是發現被過濾掉了 使用環境變量進行繞過 $a new…

IP查詢與網絡風險的關系

網絡風險場景與IP查詢的關聯 網絡攻擊、惡意行為、數據泄露等風險事件頻發&#xff0c;而IP地址作為網絡設備的唯一標識&#xff0c;承載著關鍵線索。例如&#xff0c;在DDoS惡意行為中&#xff0c;攻擊者利用大量IP地址發起流量洪泛&#xff1b;惡意行為通過變換IP地址繞過封…

pikachu通關教程-XSS

XSS XSS漏洞原理 XSS被稱為跨站腳本攻擊&#xff08;Cross Site Scripting&#xff09;&#xff0c;由于和層疊樣式表&#xff08;Cascading Style Sheets&#xff0c;CSS&#xff09;重名&#xff0c;改為XSS。主要基于JavaScript語言進行惡意攻擊&#xff0c;因為js非常靈活…

【時時三省】(C語言基礎)數組作為函數參數

山不在高&#xff0c;有仙則名。水不在深&#xff0c;有龍則靈。 ----CSDN 時時三省 調用有參函數時&#xff0c;需要提供實參。例如sin ( x )&#xff0c;sqrt ( 2&#xff0c;0 )&#xff0c;max ( a&#xff0c;b )等。實參可以是常量、變量或表達式。數組元素的作用與變量…

硬件工程師筆記——555定時器應用Multisim電路仿真實驗匯總

目錄 一 555定時器基礎知識 二、引腳功能 三、工作模式 1. 單穩態模式&#xff1a; 2. 雙穩態模式&#xff08;需要外部電路輔助&#xff09;&#xff1a; 3. 無穩態模式&#xff08;多諧振蕩器&#xff09;&#xff1a; 4. 可控脈沖寬度調制&#xff08;PWM&#xff09…

C++11特性:enum class(強枚舉類型)詳解

C11引入的 enum class&#xff08;強枚舉類型&#xff09;解決了傳統枚舉的多個問題&#xff1a; 防止枚舉值泄漏到外部作用域&#xff1b;禁止不同枚舉間的隱式轉換&#xff1b;允許指定底層數據類型優化內存&#xff1b;避免命名空間污染。 其基本語法為 enum class Name{.…

【QT】QString 與QString區別

在C中&#xff0c;QString 和 QString& 有本質區別&#xff0c;尤其是在參數傳遞和內存管理方面&#xff1a; 1. QString&#xff08;按值傳遞&#xff09; 創建副本&#xff1a;傳遞時會創建完整的字符串副本內存開銷&#xff1a;可能涉及深拷貝&#xff08;特別是大字符…

提升四級閱讀速度方法

以下是針對四級英語閱讀速度提升的系統性解決方案&#xff0c;結合最新考試規律和高效訓練方法&#xff0c;分五個核心模塊整理&#xff1a; &#x1f680; ??一、基礎提速訓練&#xff08;消除生理障礙&#xff09;?? ??擴大視幅范圍?? 從逐詞閱讀升級為 ??意群閱讀…

6.4 note

構造矩陣 class Solution { private: vector<int> empty {}; // 返回每個數字(-1)所在的序號&#xff0c;可以是行或列, 如果為空則無效 vector<int> topoSort(int k, vector<vector<int>>& conditions) { // 構建一個圖…

SCSS 全面深度解析

一、SCSS 入門指南&#xff1a;為你的 CSS 工作流注入超能力 在現代 Web 開發中&#xff0c;樣式表的復雜性和維護成本日益增加。為了應對這一挑戰&#xff0c;CSS 預處理器應運而生&#xff0c;而 SCSS (Sassy CSS) 正是其中最流行、最強大的工具之一。本指南將帶你深入了解 …

R1-Searcher++新突破!強化學習如何賦能大模型動態知識獲取?

R1-Searcher新突破&#xff01;強化學習如何賦能大模型動態知識獲取&#xff1f; 大語言模型&#xff08;LLM&#xff09;雖強大卻易因靜態知識產生幻覺&#xff0c;檢索增強生成&#xff08;RAG&#xff09;技術成破局關鍵。本文將解讀R1-Searcher框架&#xff0c;看其如何通…