設計模式——簡單工廠模式(創建型)

摘要

本文主要介紹了簡單工廠模式,包括其定義、結構、實現方式、適用場景、實戰示例以及思考。簡單工廠模式是一種創建型設計模式,通過工廠類根據參數決定創建哪一種產品類的實例,封裝了對象創建的細節,使客戶端無需關心具體類的創建邏輯。文章詳細闡述了其角色組成、類圖、時序圖,探討了兩種常見的實現方式,分析了適合與不適合的場景,并提供了 Spring 項目和可插拔式策略工廠的實戰示例。最后,還提出了支持 SPI 機制、注解標記策略名稱和配置中心切換策略等思考方向。

1. 簡單工廠模式定義

簡單工廠模式是一種創建型設計模式,它通過一個工廠類根據傳入的參數決定創建哪一種產品類的實例

核心要點:

  • 核心角色:工廠類(Factory)
    • 負責創建產品對象。
    • 客戶端只需傳遞參數,不關心具體類的創建邏輯。
  • 目標:封裝對象創建的細節,將創建對象的邏輯從使用者中分離出來。

組成結構:

角色

說明

Product

抽象產品類(接口或抽象類)

ConcreteProduct

具體產品類,實現 Product 接口

Factory

工廠類,包含創建產品對象的靜態方法

Client

客戶端,調用工廠方法獲取產品對象并使用它

2. 簡單工廠模式結構

2.1. 簡單工廠類圖

2.2. 簡單工廠時序圖

3. 簡單工廠模式實現方式

實現方式主要分為兩種:

實現方式

描述

1. 靜態方法創建(常用)

工廠方法是 static的,客戶端直接通過類名調用,無需實例化工廠

2. 實例方法創建(靈活)

工廠需要先實例化,再調用方法創建對象,適合支持不同配置或依賴注入

3.1. ? 實現方式 1:靜態方法創建產品對象(最常見)

// 抽象產品
public interface Product {void doWork();
}// 具體產品 A
public class ProductA implements Product {public void doWork() {System.out.println("產品A正在工作");}
}// 具體產品 B
public class ProductB implements Product {public void doWork() {System.out.println("產品B正在工作");}
}// 簡單工廠
public class SimpleFactory {public static Product createProduct(String type) {if ("A".equalsIgnoreCase(type)) {return new ProductA();} else if ("B".equalsIgnoreCase(type)) {return new ProductB();}throw new IllegalArgumentException("不支持的產品類型:" + type);}
}// 客戶端
public class Client {public static void main(String[] args) {Product product = SimpleFactory.createProduct("A");product.doWork();  // 輸出:產品A正在工作}
}

3.2. ? 實現方式 2:使用工廠實例方法創建產品對象(便于配置)

// 工廠類
public class SimpleFactory {public Product createProduct(String type) {if ("A".equalsIgnoreCase(type)) {return new ProductA();} else if ("B".equalsIgnoreCase(type)) {return new ProductB();}throw new IllegalArgumentException("不支持的產品類型:" + type);}
}// 客戶端
public class Client {public static void main(String[] args) {SimpleFactory factory = new SimpleFactory();Product product = factory.createProduct("B");product.doWork();  // 輸出:產品B正在工作}
}

3.3. 🧠 簡單工廠實現總結

對比項

靜態方法工廠

實例方法工廠

是否需要工廠對象

是否支持配置

較差

支持通過構造函數注入

使用場景

通用工廠、工具類

多配置或狀態的工廠類

4. 簡單工廠模式適合場景

4.1. ? 適合的場景(推薦使用簡單工廠):

場景描述

原因

產品種類有限,變化不大

工廠中 if-else/switch 可維護性尚可,結構清晰

客戶端不關心對象創建細節

封裝了具體類的創建過程,減少耦合

多個子類實現一個接口/抽象類,客戶端按條件選擇創建哪一個

工廠根據傳參決定具體返回哪個子類

代碼結構相對簡單,開發階段處于初期

不想引入復雜設計,簡單工廠最直觀、易懂

希望集中管理對象創建

比 scattered new 更好維護和修改

📌 示例:日志輸出、支付方式選擇、消息發送器選擇(短信/郵件/微信)等。

4.2. ? 不適合的場景(不推薦使用簡單工廠):

場景描述

問題

1. 產品種類經常變化或增加

每新增一個產品都要修改工廠類,違反“開放封閉原則”

2. 產品種類太多,邏輯復雜

工廠類會膨脹成一個巨大類,不利于維護

3. 需要依賴注入、構造過程復雜

無法靈活注入依賴,缺乏拓展性

4. 對產品創建過程有定制要求

不能對不同產品的創建過程進行細粒度控制

5. 分布式、多模塊開發場景

集中式工廠類會形成模塊間強依賴,不利于解耦和部署

📌 示例:大型系統中涉及復雜對象生命周期控制的場景(如數據庫連接池、線程池、配置驅動類等)。

4.3. ? 使用建議總結:

建議

原因

? 使用于產品穩定、變化少的小規模項目

簡單、易維護

? 不建議用于大型、產品體系復雜的項目

違背開閉原則、擴展性差

👉 可結合工廠方法模式或抽象工廠模式演進

更好地支持擴展與解耦

5. 簡單工廠模式實戰示例

5.1. Spring項目中簡單工廠示例

我們以“消息發送系統”為例,演示如何使用簡單工廠根據輸入創建不同的消息發送器(如短信、郵件、微信等)。

5.1.1. ? 場景目標

在 Spring 項目中,根據配置選擇不同的消息發送器進行發送,如:

  • 配置為 sms:發送短信;
  • 配置為 email:發送郵件;
  • 配置為 wechat:發送微信。

5.1.2. ? 定義統一接口

public interface MessageSender {void send(String message);
}

5.1.3. ? 三種發送器的實現類

@Component("smsSender")
public class SmsSender implements MessageSender {public void send(String message) {System.out.println("發送短信:" + message);}
}@Component("emailSender")
public class EmailSender implements MessageSender {public void send(String message) {System.out.println("發送郵件:" + message);}
}@Component("wechatSender")
public class WechatSender implements MessageSender {public void send(String message) {System.out.println("發送微信:" + message);}
}

5.1.4. ? 簡單工廠類(使用 Spring 容器管理)

@Component
public class MessageSenderFactory {@Autowiredprivate ApplicationContext applicationContext;public MessageSender createSender(String type) {switch (type.toLowerCase()) {case "sms":return applicationContext.getBean("smsSender", MessageSender.class);case "email":return applicationContext.getBean("emailSender", MessageSender.class);case "wechat":return applicationContext.getBean("wechatSender", MessageSender.class);default:throw new IllegalArgumentException("不支持的消息類型:" + type);}}
}

5.1.5. ? 使用示例(Controller 或 Service)

@Service
public class NotifyService {@Autowiredprivate MessageSenderFactory messageSenderFactory;// 模擬從配置文件或參數中讀取類型@Value("${message.type:sms}")private String messageType;public void notifyUser(String content) {MessageSender sender = messageSenderFactory.createSender(messageType);sender.send(content);}
}

5.1.6. ? 應用入口(或 Controller)

@RestController
public class MessageController {@Autowiredprivate NotifyService notifyService;@GetMapping("/send")public String send(@RequestParam String msg) {notifyService.notifyUser(msg);return "消息已發送";}
}

5.1.7. ? application.yml 示例配置

message:type: email

5.1.8. ? 簡單工廠示例總結

設計點

說明

工廠類

MessageSenderFactory是核心簡單工廠類

接口統一

所有發送器實現 MessageSender接口

解耦

NotifyService不依賴具體實現類,依賴工廠和接口

可配置

支持通過配置控制行為,符合 Spring 項目實踐

5.2. 可插拔式策略工廠(使用 SPI、Map 注冊) 示例

下面是一個 可插拔式策略工廠(基于 Map 注冊 + Spring 管理) 的完整示例,非常適用于需要動態切換、按配置擴展的業務策略類,比如:消息發送、支付渠道、風控策略、營銷活動處理器等實現一種 靈活可擴展 的策略選擇工廠,每個策略自動注冊 到一個 Map<String, Strategy> 中,不需要手動 switch-case

5.2.1. ? 定義統一接口(策略接口)

public interface MessageSender {String type(); // 每個實現類提供自己的標識void send(String message);
}

5.2.2. ? 三種發送實現類(@Component 自動注入)

@Component
public class SmsSender implements MessageSender {public String type() {return "sms";}public void send(String message) {System.out.println("【短信】發送:" + message);}
}@Component
public class EmailSender implements MessageSender {public String type() {return "email";}public void send(String message) {System.out.println("【郵件】發送:" + message);}
}@Component
public class WechatSender implements MessageSender {public String type() {return "wechat";}public void send(String message) {System.out.println("【微信】發送:" + message);}
}

5.2.3. ? 自動注冊策略工廠(Map 注冊方式)

@Component
public class MessageSenderFactory {private final Map<String, MessageSender> senderMap = new HashMap<>();// Spring 會自動注入所有 MessageSender 的實現類@Autowiredpublic MessageSenderFactory(List<MessageSender> senders) {for (MessageSender sender : senders) {senderMap.put(sender.type(), sender);}}public MessageSender getSender(String type) {MessageSender sender = senderMap.get(type);if (sender == null) {throw new IllegalArgumentException("不支持的消息類型: " + type);}return sender;}
}

5.2.4. ? 使用策略工廠的服務類

@Service
public class NotifyService {@Autowiredprivate MessageSenderFactory messageSenderFactory;public void notifyUser(String type, String content) {MessageSender sender = messageSenderFactory.getSender(type);sender.send(content);}
}

5.2.5. ? Controller 示例

@RestController
@RequestMapping("/msg")
public class MessageController {@Autowiredprivate NotifyService notifyService;@GetMapping("/send")public String send(@RequestParam String type, @RequestParam String msg) {notifyService.notifyUser(type, msg);return "消息已發送";}
}

5.2.6. ? 示例調用

請求:

GET /msg/send?type=sms&msg=Hello_SMS
GET /msg/send?type=email&msg=Hello_Email
GET /msg/send?type=wechat&msg=Hello_WeChat

輸出:

【短信】發送:Hello_SMS
【郵件】發送:Hello_Email
【微信】發送:Hello_WeChat

5.2.7. 🚀 可插拔式策略工廠優勢總結

特性

說明

可插拔

新增一個實現類即可生效,無需改動工廠或業務代碼

高擴展性

支持多策略、動態注冊

易維護

擺脫 if-else / switch

Spring友好

利用 Spring 自動注入 & 生命周期

5.3. 🔌 簡單工廠設計模式可拓展方向(高級)

  • 支持 SPI 機制(META-INF/services),用于插件式加載(可用于 jar 擴展、熱插拔);
  • 支持 注解標記策略名稱
  • 支持配置中心切換策略,如使用 @Value("${message.type}") 注入默認策略。

6. 簡單工廠模式思考

6.1. 支持 SPI 機制(META-INF/services),用于插件式加載(可用于 jar 擴展、熱插拔);

下面是一個完整的 基于 Java SPI(Service Provider Interface)機制的插件式策略工廠實現示例,它常用于實現模塊解耦、可插拔、動態擴展功能。以“消息發送策略”為例,不使用 Spring 注解掃描,而是通過 SPI 機制動態加載所有實現類。

6.1.1. 🧩 定義 SPI 接口(策略接口)

// src/main/java/com/example/spi/MessageSender.java
package com.example.spi;public interface MessageSender {String type();             // 返回類型標識符void send(String message); // 發送消息邏輯
}

6.1.2. 📝 實現類(位于獨立模塊 / jar 中)

// src/main/java/com/example/impl/SmsSender.java
package com.example.impl;import com.example.spi.MessageSender;public class SmsSender implements MessageSender {@Overridepublic String type() {return "sms";}@Overridepublic void send(String message) {System.out.println("【短信發送】" + message);}
}

6.1.3. 🗂? 3SPI 注冊文件

在 jar 包中的 resources/META-INF/services/ 路徑下創建文件:

META-INF/services/com.example.spi.MessageSender

內容如下(每一行一個實現類的全限定名):

com.example.impl.SmsSender

? 當你有多個策略實現時,添加多行即可,如:

com.example.impl.SmsSender
com.example.impl.EmailSender

6.1.4. ?? 工廠類:動態加載所有策略實現

package com.example.factory;import com.example.spi.MessageSender;import java.util.*;public class MessageSenderFactory {private final Map<String, MessageSender> senderMap = new HashMap<>();public MessageSenderFactory() {// 加載spi接口所有接口實現類ServiceLoader<MessageSender> loader = ServiceLoader.load(MessageSender.class);for (MessageSender sender : loader) {senderMap.put(sender.type(), sender);}}public MessageSender getSender(String type) {MessageSender sender = senderMap.get(type);if (sender == null) {throw new IllegalArgumentException("不支持的消息類型: " + type);}return sender;}
}
ServiceLoader<MessageSender> loader = ServiceLoader.load(MessageSender.class);

Java 原生 SPI(Service Provider Interface)機制 的核心。它的底層原理其實并不復雜,是通過讀取類路徑下的 META-INF/services/ 目錄下的文件,并利用反射機制加載實現類。以下是 ServiceLoader 的簡化執行邏輯:

// 從 META-INF/services/ 下查找接口對應的配置文件
Enumeration<URL> urls = classLoader.getResources("META-INF/services/" + serviceClass.getName());// 讀取文件中的類名
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
String implClassName = reader.readLine();// 通過反射實例化對象
Class<?> clazz = Class.forName(implClassName);
Object instance = clazz.newInstance();

每個實現類會被加載成一個對象,并返回一個延遲加載的迭代器。

6.1.5. 🧪 使用示例(main 方法中調用)

public class Main {public static void main(String[] args) {MessageSenderFactory factory = new MessageSenderFactory();MessageSender sender = factory.getSender("sms");sender.send("Hello SPI!");}
}

6.1.6. 🎯 整體結構

src/
├── main/
│   ├── java/
│   │   ├── com.example.spi/MessageSender.java
│   │   ├── com.example.impl/SmsSender.java
│   │   └── com.example.factory/MessageSenderFactory.java
│   └── resources/
│       └── META-INF/services/com.example.spi.MessageSender

6.1.7. 📌 SPI 模式的優點

優點

說明

插件化、低耦合

實現類可來自外部 jar 包,主程序不需修改

動態擴展能力強

實現類可以熱插拔(配合 OSGi、模塊系統)

框架內部廣泛使用

Dubbo、JDBC、Spring Boot 自動配置(spring.factories

6.1.8. 🚫 注意事項

  • SPI 默認是懶加載 + 非線程安全(如有并發需求請做好緩存);
  • IDE 無法提示類名(注冊文件中填寫錯誤 IDE 不會報警);
  • 多個 jar 中存在相同接口實現可能沖突;
  • 如果你使用的是 SpringBoot,推薦改用 Spring 的 SPI(如 spring.factoriesspring.factoriesspring/org.springframework.boot.autoconfigure.EnableAutoConfiguration)機制配合。

6.2. 支持注解標記策略名稱

策略模式 中,支持通過 注解 來標記每個策略的名稱,可以極大提升策略類的可讀性和擴展性,尤其適用于 SPI、Map 注冊、Spring 容器注冊等場景。

  • 多個 MessageSender 策略實現類
  • 每個類通過注解標記其類型名稱(如 @MessageType("sms")
  • 使用 Map 注冊所有策略,支持動態獲取

6.2.1. ? 定義注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MessageType {String value();  // 策略類型標識
}

6.2.2. ? 定義接口

public interface MessageSender {void send(String message);
}

6.2.3. ? 實現策略類 + 注解標記

@MessageType("sms")
public class SmsSender implements MessageSender {@Overridepublic void send(String message) {System.out.println("發送短信: " + message);}
}@MessageType("email")
public class EmailSender implements MessageSender {@Overridepublic void send(String message) {System.out.println("發送郵件: " + message);}
}

6.2.4. ? 自動注冊工廠類(注解掃描)

public class MessageSenderFactory {private final Map<String, MessageSender> senderMap = new HashMap<>();public MessageSenderFactory() {// SPI 加載所有 MessageSender 實現類ServiceLoader<MessageSender> loader = ServiceLoader.load(MessageSender.class);for (MessageSender sender : loader) {MessageType annotation = sender.getClass().getAnnotation(MessageType.class);if (annotation != null) {senderMap.put(annotation.value(), sender);}}}public MessageSender getSender(String type) {MessageSender sender = senderMap.get(type);if (sender == null) {throw new IllegalArgumentException("不支持的消息類型: " + type);}return sender;}
}

6.2.5. ? 使用示例

public class Main {public static void main(String[] args) {MessageSenderFactory factory = new MessageSenderFactory();factory.getSender("sms").send("驗證碼123456");factory.getSender("email").send("歡迎郵件");}
}

6.2.6. ? 優點

  • 注解直觀標記類型,無需硬編碼注冊
  • 擴展一個新策略只需添加一個類并標注注解
  • ServiceLoader/Spring 配合使用,支持動態發現

6.3. 支持配置中心切換策略,如使用 @Value("${message.type}") 注入默認策略。

你希望實現一種 支持配置中心動態切換策略 的能力,例如通過配置中心的屬性(如 Nacos、Apollo、Spring Cloud Config 等)控制當前策略的類型:實現思路(Spring + 注解 + Map 注冊 + 配置驅動)

6.3.1. ? 定義策略注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MessageType {String value();
}

6.3.2. ? 定義通用接口

public interface MessageSender {void send(String message);
}

6.3.3. ? 多個策略實現類

@Component
@MessageType("sms")
public class SmsSender implements MessageSender {public void send(String message) {System.out.println("發送短信: " + message);}
}@Component
@MessageType("email")
public class EmailSender implements MessageSender {public void send(String message) {System.out.println("發送郵件: " + message);}
}

6.3.4. ? 策略工廠(Spring 容器自動注冊 + 配置驅動)

@Component
public class MessageSenderFactory implements InitializingBean {@Value("${message.type:email}")  // 默認email,可由配置中心動態更新private String defaultType;@Autowiredprivate List<MessageSender> senderList;private final Map<String, MessageSender> senderMap = new HashMap<>();@Overridepublic void afterPropertiesSet() {for (MessageSender sender : senderList) {MessageType annotation = sender.getClass().getAnnotation(MessageType.class);if (annotation != null) {senderMap.put(annotation.value(), sender);}}}/** 如果使用默認方式,采用的就是nacos 配置策略*/public MessageSender getSender() {MessageSender sender = senderMap.get(defaultType);if (sender == null) {throw new IllegalArgumentException("未找到對應的策略類型: " + defaultType);}return sender;}/** 使用入參對應的策略*/public MessageSender getSender(String type) {MessageSender sender = senderMap.get(type);if (sender == null) {throw new IllegalArgumentException("未找到對應的策略類型: " + type);}return sender;}
}

6.3.5. ? 使用示例

@RestController
public class MessageController {@Autowiredprivate MessageSenderFactory factory;/** 如果使用默認方式,采用的就是nacos配置策略*/@GetMapping("/send")public String send(@RequestParam String msg) {factory.getSender().send(msg);return "消息已發送";}/** 如果使用入參對應方式發送*/@GetMapping("/email/send")public String send(@RequestParam String sendType, @RequestParam String msg) {factory.getSender(sendType).send(msg);return "消息已發送";}
}

6.3.6. ? 配置變更如何生效(支持熱刷新)?

如果你使用配置中心(如 Nacos),你還可以讓 @Value("${message.type}") 自動刷新:

@RefreshScope
@Component
public class MessageSenderFactory implements InitializingBean {...
}

這樣,在 Nacos 修改 message.type=emailsms,會實時切換策略。

6.3.7. ? 總結優勢

特性

實現方式

策略標識

注解 @MessageType

掃描所有策略實現

Spring 注入 List<>

配置驅動選擇策略

@Value("${message.type}")

動態刷新策略選擇

@RefreshScope+ Nacos

6.4. 使用SPI 機制(META-INF/services),用于插件式加載(可用于 jar 擴展、熱插拔);與普通簡單工廠方法實現區別?

使用 SPI 機制(META-INF/services普通簡單工廠模式 都是實現“根據類型返回不同實現類”的策略工廠思想,但它們在實現機制、應用場景和擴展性上有很大不同。以下是詳細對比和說明:

6.4.1. 🔍 核心區別對比表

項目

SPI機制(ServiceLoader

簡單工廠模式(自己注冊/Map)

加載方式

JDK 內置 ServiceLoader

自動發現實現類

自己手動注冊,或用注解 + Spring 掃描

實現類注冊位置

META-INF/services/接口全類名

代碼中通過 Map<String, Object>

是否依賴容器(如Spring)

否(純 JDK 原生機制)

是(通常依賴 Spring 注入、配置)

擴展性(插件支持)

強,可動態加入 jar 包擴展實現

弱,必須修改代碼或重啟注冊邏輯

熱插拔能力

支持(添加 jar 即生效,重啟可用)

不支持,必須重啟或改代碼

類型標識方式

實現類自己定義類型(如 type()方法)

通常用注解或手動 put(key, impl)

適合插件機制

? 非常適合

? 不適合

使用門檻

中(需要手動寫 SPI 配置文件)

低(代碼中實現注冊)

6.4.2. 🧩 SPI機制(JDK ServiceLoader)工作原理

  • 你要做的:
    1. 定義一個接口,比如:MessageSender
    2. 實現多個類,比如:EmailSenderSmsSender 并實現該接口
    3. resources/META-INF/services/com.example.spi.MessageSender 文件中列出所有實現類的 全限定類名
com.example.sender.EmailSender
com.example.sender.SmsSender
  • 運行時使用 ServiceLoader 自動掃描并實例化:
ServiceLoader<MessageSender> loader = ServiceLoader.load(MessageSender.class);
for (MessageSender sender : loader) {senderMap.put(sender.type(), sender);
}

📦 實現類可以是外部 jar 包,插件式部署。無需改主程序代碼。

6.4.3. 🛠? 簡單工廠模式實現方式

實現邏輯通常在代碼里“硬編碼”注冊每種類型與實現類的關系:

public class SenderFactory {private static final Map<String, MessageSender> map = new HashMap<>();static {map.put("email", new EmailSender());map.put("sms", new SmsSender());}public static MessageSender getSender(String type) {return map.get(type);}
}

🧱 實現類和工廠強耦合,新增類型時,必須改代碼、重編、重新部署。

6.4.4. 🚦 使用場景對比

場景

建議使用方式

插件式架構,第三方擴展點

? 使用 SPI

配置中心控制策略選擇

? 使用 Spring + Map

內部服務、類型少且固定

? 簡單工廠

支持 jar 級別熱插拔、可拔插插件

? SPI + jar 模塊化

多環境配置動態選擇實現

? Spring 結合 @Value

7. 博文參考

  • 1. 簡單工廠模式( Simple Factory Pattern ) — Graphic Design Patterns
  • 創建型 - 簡單工廠(Simple Factory) | Java 全棧知識體系

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

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

相關文章

抽象工廠模式與策略模式結合使用小案例

目錄 1.前言1.示例說明1.1定義通用接口1.2 定義抽象工廠1.3 支付寶實現1.4 微信實現1.5 客戶端使用代碼&#xff08;組合使用&#xff09;1.6 示例結果輸出1.7 總結 1.前言 上一篇章就通過簡單的案例來了解抽象工廠模式和策略模式的使用&#xff0c;現在就用個支付場景的小案例…

通過WiFi無線連接小米手機攝像頭到電腦的方法

通過WiFi無線連接小米手機攝像頭到電腦的方法 以下是基于Scrcpy和DroidCam兩種工具的無線連接方案&#xff0c;需提前完成開發者模式與USB調試的開啟&#xff08;參考原教程步驟&#xff09;&#xff1a; 方法一&#xff1a;Scrcpy無線投屏&#xff08;無需手機端安裝&#xf…

2025軟件供應鏈安全最佳實踐︱證券DevSecOps下供應鏈與開源治理實踐

項目背景&#xff1a;近年來&#xff0c;云計算、AI人工智能、大數據等信息技術的不斷發展、各行各業的信息電子化的步伐不斷加快、信息化的水平不斷提高&#xff0c;網絡安全的風險不斷累積&#xff0c;金融證券行業面臨著越來越多的威脅挑戰。特別是近年以來&#xff0c;開源…

Java高級 | 【實驗二】Springboot 控制器類+相關注解知識

隸屬文章&#xff1a; Java高級 | &#xff08;二十二&#xff09;Java常用類庫-CSDN博客 系列文章&#xff1a; Java高級 | 【實驗一】Spring Boot安裝及測試 最新-CSDN博客 目錄 一、MVC模式 二、SpringBoot基礎——控制層Controller詳解 &#xff08;一&#xff09;主要工…

MySQL 事務深度解析:面試核心知識點與實戰

&#x1f91f;致敬讀者 &#x1f7e9;感謝閱讀&#x1f7e6;笑口常開&#x1f7ea;生日快樂?早點睡覺 &#x1f4d8;博主相關 &#x1f7e7;博主信息&#x1f7e8;博客首頁&#x1f7eb;專欄推薦&#x1f7e5;活動信息 文章目錄 Java 中 MySQL 事務深度解析&#xff1a;面試…

【趣味Html】第11課:動態閃爍發光粒子五角星

打造炫酷的動態閃爍發光粒子五角星效果 前言 在現代Web開發中&#xff0c;視覺效果的重要性不言而喻。今天我們將深入探討如何使用HTML5 Canvas和JavaScript創建一個令人驚艷的動態閃爍發光粒子五角星效果。這個項目不僅展示了Canvas的強大功能&#xff0c;還涉及了粒子系統、…

6.RV1126-OPENCV 形態學基礎膨脹及腐蝕

一.膨脹 1.膨脹原理 膨脹的本質就是通過微積分的轉換&#xff0c;將圖像A和圖形B進行卷積操作合并成一個AB圖像。核就是指任意的形狀或者大小的圖形B。例如下圖&#xff0c;將核(也就是圖形B)通過微積分卷積&#xff0c;和圖像A合并成一個圖像AB。 2.特點 圖像就會更加明亮 …

機器學習實戰37-基于情感字典和機器學習的股市輿情分析可視化系統

文章目錄 一、項目背景數字時代情感分析情況二、項目流程1.數據采集與預處理2.復合情感分析模型構建3.輿情分析可視化:三、機器學習算法原理1.支持向量機基礎2.核函數與高維映射3.情感分類特征融合4.模型訓練與優化四、實現代碼五、系統特點與優勢1.復合情感分析模型2.多維度可…

STM32F407VET6學習筆記9:編譯輸出固定大小.bin文件

今日學習如何輸出固定大小的.bin編譯文件 目錄 Keil_V5 fromelf.exe 軟件目錄&#xff1a; 魔棒添加命令輸出bin文件&#xff1a; 輸出固定大小的bin文件&#xff1a; 計算bin文件大小&#xff1a; 安裝 SRecord 工具集&#xff1a; 使用SRecord&#xff1a; 參考文章&#…

【Web應用】若依框架:基礎篇14 源碼閱讀-后端代碼分析

文章目錄 ?前言?一、課程講解?總結 標題詳情作者JosieBook頭銜CSDN博客專家資格、阿里云社區專家博主、軟件設計工程師博客內容開源、框架、軟件工程、全棧&#xff08;,NET/Java/Python/C&#xff09;、數據庫、操作系統、大數據、人工智能、工控、網絡、程序人生口號成為你…

Java 單例模式詳解

目錄 1. 餓漢式&#xff08;Eager Initialization&#xff09; 2. 懶漢式&#xff08;Lazy Initialization&#xff09; 3. 懶漢式 同步鎖&#xff08;線程安全&#xff09; 4. 雙重檢查鎖&#xff08;Double-Checked Locking&#xff09; 5. 靜態內部類&#xff08;推薦…

從 AMQP 到 RabbitMQ:核心組件設計與工作原理(一)

一、引言 ** 在當今分布式系統盛行的時代&#xff0c;消息隊列作為一種關鍵的中間件技術&#xff0c;承擔著系統間異步通信、解耦和削峰填谷的重要職責。AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;作為一種高級消息隊列協議&#xff0c;為消息隊列的實現…

概率單純形(Probability Simplex)

目錄 定義性質在統計學中的應用在機器學習中的應用在信息論中的應用在優化問題中的應用在其他領域的應用 定義 定義&#xff1a;在數學中&#xff0c;概率單純形&#xff08;Probability Simplex&#xff09;是指在 n n n維空間中&#xff0c;所有分量非負且分量之和為1的向量…

項目練習:Vue2中el-button上的@click事件失效

文章目錄 一、問題描述二、解決 一、問題描述 button按鈕上綁定了一個click事件 對應的方法寫在methods中 但是&#xff0c;測試點擊時&#xff0c;無法觸發函數 二、解決 1、問題代碼 <el-buttonclick"changeConfirm(Y)"type"success"plainicon&qu…

十六、【前端強化篇】完善 TestCase 編輯器:支持 API 結構化定義與斷言配置

【前端強化篇】完善 TestCase 編輯器:支持 API 結構化定義與斷言配置 前言準備工作第一步:更新前端 `TestCase` 類型定義第二步:改造 `TestCaseEditView.vue` 表單第三步:修改后端代碼中的TestCase模型和序列化器第四步:測試強化后的用例編輯器總結前言 在之前的后端文章…

HTTP連接管理——短連接,長連接,HTTP 流水線

連接管理是一個 HTTP 的關鍵話題&#xff1a;打開和保持連接在很大程度上影響著網站和 Web 應用程序的性能。在 HTTP/1.x 里有多種模型&#xff1a;短連接、_長連接_和 HTTP 流水線。 下面分別來詳細解釋 短連接 HTTP 協議最初&#xff08;0.9/1.0&#xff09;是個非常簡單的…

MySQL范式和反范式

范式 是用一組規則定義的數據庫設計標準&#xff0c;旨在確保數據庫結構合理&#xff0c;避免數據冗余和異常。 目的 消除數據的重復&#xff0c;提高存儲效率防止數據異常&#xff08;插入、刪除、更新異常&#xff09;提高數據的完整性和一致性 第一范式 定義 所有列&am…

編程技能:格式化打印04,sprintf

專欄導航 本節文章分別屬于《Win32 學習筆記》和《MFC 學習筆記》兩個專欄&#xff0c;故劃分為兩個專欄導航。讀者可以自行選擇前往哪個專欄。 &#xff08;一&#xff09;WIn32 專欄導航 上一篇&#xff1a;編程技能&#xff1a;格式化打印03&#xff0c;printf 回到目錄…

JavaScript性能優化實戰:深入探討JavaScript性能瓶頸與優化技巧

引言:為什么JavaScript性能至關重要 在現代Web開發中,JavaScript已成為構建交互式應用程序的核心技術。隨著單頁應用(SPA)和復雜前端架構的普及,JavaScript代碼的性能直接影響用戶體驗、轉化率甚至搜索引擎排名。研究表明,頁面加載時間每增加1秒,轉化率可能下降7%,而性能…

Java數據結構——八大排序

排序 插?排序希爾排序直接選擇排序堆排序冒泡排序快速排序歸并排序計數排序 排序的概念 排序&#xff1a;就是將一串東西&#xff0c;按照要求進行排序&#xff0c;按照遞增或遞減排序起來 穩定性&#xff1a;就是比如排序中有兩個相同的數&#xff0c;如果排序后&#xff0c…