設計模式——策略設計模式(行為型)

摘要

策略設計模式是一種行為型設計模式,它定義了一系列算法并將每個算法封裝起來,使它們可以相互替換。該模式讓算法的變化獨立于使用算法的客戶,從而使得算法可以靈活地切換和擴展。其主要角色包括策略接口、具體策略類和環境類。策略模式的結構通過類圖和時序圖進行展示,實現方式涵蓋定義策略接口、實現具體策略類、定義環境類等步驟。它適用于多種場景,如在Spring中動態選擇策略等,同時也有其不適用的場景。實戰示例包括需求背景、策略接口及實現類、策略上下文類等,有助于理解策略模式的實際應用。

1. 策略設計模式定義

策略設計模式(Strategy Pattern)是一種行為型設計模式,它定義了一系列算法(策略),并將每個算法封裝起來,使它們可以相互替換。策略模式讓算法的變化獨立于使用算法的客戶,從而使得算法可以靈活地切換和擴展。

核心思想:將不同的算法封裝成獨立的策略類,客戶端通過調用統一的接口來選擇和執行具體的策略,而不用關心具體的實現細節。

1.1.1. 策略設計模式的主要角色:

  • 策略接口(Strategy):定義一系列算法的公共接口。
  • 具體策略類(ConcreteStrategy):實現策略接口的具體算法。
  • 環境類(Context):持有一個策略對象的引用,負責調用具體策略的方法。

2. 策略設計模式結構

策略模式包含如下角色:

  • Context: 環境類
  • Strategy: 抽象策略類
  • ConcreteStrategy: 具體策略類

2.1. 策略設計模式類圖

2.2. 策略設計模式時序圖

3. 策略設計模式實現方式

3.1. 定義策略接口(Strategy)

定義一個公共接口,聲明所有具體策略類需要實現的方法。

public interface Strategy {void execute();
}

3.2. 實現具體策略類(ConcreteStrategy)

實現策略接口的多個具體類,分別封裝不同的算法或行為。

@Component("strategyA")
public class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("執行策略 A");}
}@Component("strategyB")
public class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("執行策略 B");}
}

3.3. 定義環境類(Context)

環境類持有策略接口引用,通過調用接口的方法來執行具體策略。

@Component
public class StrategyContext {private Strategy strategy;// 通過setter注入當前使用的策略public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void executeStrategy() {strategy.execute();}
}

3.4. 在Spring中動態選擇策略

通過Spring容器自動注入所有策略類,利用策略名稱或者業務標識動態選擇執行的策略。

@Component
public class StrategyService {private final Map<String, Strategy> strategyMap;@Autowiredpublic StrategyService(Map<String, Strategy> strategyMap) {this.strategyMap = strategyMap;}public void execute(String strategyName) {Strategy strategy = strategyMap.get(strategyName);if (strategy == null) {throw new IllegalArgumentException("無效的策略名稱:" + strategyName);}strategy.execute();}
}

3.5. 使用示例(調用)


@Autowired
private StrategyService strategyService;public void test() {strategyService.execute("strategyA");  // 執行策略AstrategyService.execute("strategyB");  // 執行策略B
}

3.6. 策略模式總結

  • 策略接口定義公共方法;
  • 具體策略類實現不同算法;
  • 環境類調用策略接口;
  • Spring容器管理策略類,通過注解和自動注入動態選擇策略。

4. 策略設計模式適合場景

4.1. ? 適合使用策略設計模式的場景

場景

說明

多算法動態切換

系統中存在多種算法或行為,需要根據業務動態選擇。

避免復雜條件判斷

需要減少大量 if-else 或 switch-case 的代碼。

算法封裝與擴展

不同算法實現統一接口,方便互換和新增策略。

遵循單一職責原則

將變化的算法封裝,保持代碼清晰易維護。

支持新增策略不影響客戶端

新策略可增加而無需修改客戶端代碼,符合開閉原則。

業務規則頻繁變動

算法或業務規則經常調整,需靈活切換實現。

4.2. ? 不適合使用策略設計模式的場景

場景

原因

單一算法場景

只有一種算法,沒有多策略選擇,策略模式無意義。

算法簡單且穩定

算法邏輯簡單且變化不大,策略模式增加復雜度。

策略間依賴強

策略之間耦合較緊,無法獨立替換。

頻繁變更策略映射

頻繁修改策略注冊或映射,維護成本較高。

系統規模較小

設計復雜度不必要增加,適合直接調用簡單實現。

5. 策略設計模式實戰示例

5.1. 需求背景

假設風控系統中,有不同的風控策略(如:信用評分風控、黑名單風控、行為風控),業務根據不同場景動態選擇策略執行風控校驗。

5.2. 策略接口

public interface RiskControlStrategy {boolean checkRisk(String userId);
}

5.3. 具體策略實現類

import org.springframework.stereotype.Component;@Component("creditScoreStrategy")
public class CreditScoreStrategy implements RiskControlStrategy {@Overridepublic boolean checkRisk(String userId) {System.out.println("執行信用評分風控,用戶:" + userId);// 偽代碼:查詢用戶信用分,判斷是否高風險return true;  // 通過}
}@Component("blacklistStrategy")
public class BlacklistStrategy implements RiskControlStrategy {@Overridepublic boolean checkRisk(String userId) {System.out.println("執行黑名單風控,用戶:" + userId);// 偽代碼:判斷用戶是否在黑名單中return false; // 攔截}
}@Component("behaviorStrategy")
public class BehaviorStrategy implements RiskControlStrategy {@Overridepublic boolean checkRisk(String userId) {System.out.println("執行行為風控,用戶:" + userId);// 偽代碼:分析用戶行為風險return true;}
}

5.4. 策略上下文類(策略注冊表)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.Map;@Component
public class RiskControlStrategyContext {@Autowiredprivate Map<String, RiskControlStrategy> strategyMap;public RiskControlStrategy getStrategy(String strategyType) {return strategyMap.getOrDefault(strategyType, strategyMap.get("creditScoreStrategy"));}
}

5.5. 業務調用示例(例如 Controller 或 Service)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class RiskControlService {@Autowiredprivate RiskControlStrategyContext strategyContext;public boolean executeRiskCheck(String userId, String strategyType) {RiskControlStrategy strategy = strategyContext.getStrategy(strategyType);return strategy.checkRisk(userId);}
}

5.6. 策略模式使用示例

// 比如Controller層調用
@Autowired
private RiskControlService riskControlService;public void handleRequest(String userId, String riskType) {boolean passed = riskControlService.executeRiskCheck(userId, riskType);if (passed) {System.out.println("風控通過");} else {System.out.println("風控攔截");}
}

5.7. 總結

  • 各策略實現了統一接口,方便動態切換。
  • Spring容器自動掃描并注入所有策略,實現“策略注冊表”。
  • 業務只需調用策略上下文類,無需關心具體策略實現。
  • 支持輕松擴展,新增策略只需新增實現并標注組件注解即可。

6. 策略設計模式思考

6.1. 哪些設計模式與策略模式常用與實戰開發中?

策略設計模式常常和其他設計模式組合使用,以實現更加靈活、解耦且可擴展的系統設計。下面列出幾個策略模式常見的組合模式及其實戰意義

組合模式

作用和實戰意義

工廠模式(Factory)

工廠模式負責策略對象的創建,結合策略模式實現動態策略實例化,避免客戶端直接依賴具體策略類。

策略+工廠

通過工廠動態創建或獲取策略實例,簡化策略管理,便于新增策略。

策略+責任鏈模式

多個策略按責任鏈順序依次執行,適合風控流程中多步校驗和規則鏈式處理。

策略+裝飾器模式

在策略的基礎上動態添加額外行為(如日志、緩存、權限控制),增強策略功能。

策略+模板方法模式

模板方法定義固定流程,策略負責具體步驟的算法實現,二者分工清晰,靈活替換。

策略+橋接模式

橋接模式分離策略接口與實現,策略作為抽象層一部分,便于獨立擴展和變化。

策略+命令模式

命令模式封裝請求,策略定義請求的處理算法,便于請求調用與執行分離。

策略+觀察者模式

觀察者模式監聽策略執行結果,實現事件驅動的策略調整和聯動處理。

策略+代理模式

代理在調用策略前后添加橫切邏輯,如權限檢查、性能統計。

策略+狀態模式

狀態模式控制狀態切換,策略定義每狀態下的具體行為。

簡單示例說明

  • 策略 + 工廠:風控策略的工廠負責創建或注入具體策略,客戶端通過工廠獲取策略實例。
  • 策略 + 責任鏈:風控中,多個風控策略組成責任鏈,一個接一個執行直到攔截或全部通過。
  • 策略 + 裝飾器:對某個策略加日志功能或緩存功能,用裝飾器包裝策略實例。

博文參考

  • 5. 策略模式 — Graphic Design Patterns
  • 策略設計模式

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

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

相關文章

DeepSeek-R1-0528,官方的端午節特別獻禮

DeepSeek&#xff1a;端午安康&#xff01;刻在國人骨子里的浪漫 2025 年 05 月 28 日 | DeepSeek 端午特別獻禮 當粽葉飄香時&#xff0c;DeepSeek 悄然帶來一份節日驚喜 版本號 DeepSeek-R1-0528 正式上線 官方賦予它的靈魂是&#xff1a; 思考更深 推理更強 用戶通過官網…

mac安裝brew時macos無法信任ruby的解決方法

背景 在使用如下腳本安裝brew時&#xff0c;遇到安裝ruby&#xff0c;macos不信任外部軟件&#xff0c;在安全性點擊信任仍然無法安裝。 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"如何解決 本地安裝好符…

2025音頻傳輸模塊全球選購指南:高品質音頻體驗的品牌之選

隨著無線技術的迅猛發展&#xff0c;音頻傳輸模塊&#xff08;Audio Transmission Module&#xff09;已成為高品質音頻體驗的關鍵技術之一。它們廣泛應用于智能家居、無線耳機、會議系統、廣播設備以及專業音頻領域。面對市場上多樣化的產品&#xff0c;如何選擇適合自己需求的…

解析樓宇自控系統:分布式結構的核心特點與優勢展現

在建筑智能化發展的進程中&#xff0c;樓宇自控系統作為實現建筑高效運行與管理的關鍵&#xff0c;其系統結構的選擇至關重要。傳統的集中式樓宇自控系統在面對日益復雜的建筑環境和多樣化的管理需求時&#xff0c;逐漸暴露出諸多弊端&#xff0c;如可靠性低、擴展性差、響應速…

Spring Boot對一些技術框架進行了統一版本號管理

這個說法是 正確的。 Spring Boot 對許多常用依賴進行了版本管理&#xff0c;因此在項目中引入這些依賴時&#xff0c;通常不需要指定版本號。 Spring Boot 依賴版本管理 &#x1f6e0;? spring-boot-starter-parent&#xff1a;當你的項目在 pom.xml (Maven 項目) 中繼承自…

關于MySQL的索引

一、索引 1、索引概述 1.1、介紹 索引&#xff08; index &#xff09;是幫助 MySQL 高效獲取數據的數據結構 ( 有序 ) 。在數據之外&#xff0c;數據庫系統還維護著滿足特定查找算法的數據結構&#xff0c;這些數據結構以某種方式引用&#xff08;指向&#xff09;數據&…

微服務常用日志追蹤方案:Sleuth + Zipkin + ELK

在微服務架構中&#xff0c;一個用戶請求往往需要經過多個服務的協同處理。為了有效追蹤請求的完整調用鏈路&#xff0c;需要一套完整的日志追蹤方案。Sleuth Zipkin ELK 組合提供了完整的解決方案 Sleuth&#xff1a;生成和傳播追蹤IDZipkin&#xff1a;收集、存儲和可視化…

R語言基礎| 創建數據集

在R語言中&#xff0c;有多種數據類型&#xff0c;用以存儲和處理數據。每種數據類型都有其特定的用途和操作函數&#xff0c;使得R語言在處理各種數據分析任務時非常靈活和強大&#xff1a; 向量&#xff08;Vector&#xff09;: 向量是R語言中最基本的數據類型&#xff0c;它…

nssctf第二題[SWPUCTF 2021 新生賽]簡簡單單的邏輯

這是題目&#xff0c;下載后得到一個python文件,打開 解讀代碼&#xff1a; for i in range(len(list)):key (list[i]>>4)((list[i] & 0xf)<<4)result str(hex(ord(flag[i])^key))[2:].zfill(2)list[i]>>4&#xff1a;從列表中取數字同時高4位向右位…

mysql(十五)

目錄 子查詢 1.準備工作 2--創建表格 3--插入數據 2.where 子查詢單列單個數據 格式 查詢 3.where 子查詢單列多個數據(in) 格式 查詢 使用子查詢 4.from 多行多數據 格式 查詢 子查詢 將select的查詢的返回結果 當成另外一個selet語句的內容去使用。 子查詢放在()里面 注意…

【HarmonyOS 5】鴻蒙Taro跨端框架

?Taro跨端框架? 支持React語法開發鴻蒙應用&#xff0c;架構分為三層&#xff1a; ArkVM層運行業務代碼和React核心TaroElement樹處理節點創建和屬性綁定TaroRenderNode虛擬節點樹與上屏節點一一對應 import { Component } from tarojs/taro export default class MyCompon…

華為OD機試真題——會議接待 /代表團坐車(2025A卷:200分)Java/python/JavaScript/C++/C語言/GO六種最佳實現

2025 A卷 200分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析; 并提供Java、python、JavaScript、C++、C語言、GO六種語言的最佳實現方式! 本文收錄于專欄:《2025華為OD真題目錄+全流程解析/備考攻略/經驗分享》 華為OD機試真題《會議…

C語言---動態內存管理、柔性數組

一、malloc和free 1、變長數組 變長數組是指數組的大小可以通過變量來指定。 在c99以及之后的標準中&#xff1a; #include<stdio.h> int main() { int n0; scanf("%d",&n); } 2、malloc和free 這個函數向內存申請一塊連續可用的空間&#xff0c;并返…

WEBSTORM前端 —— 第3章:移動 Web —— 第4節:移動適配-VM

目錄 一、適配方案 二、VM布局 ?編輯 三、vh布局 四、案例—酷我音樂 一、適配方案 二、VM布局 三、vh布局 四、案例—酷我音樂

Dynamics 365 Business Central AI Sales Order Agent Copilot

#AI Copilot# #D365 BC 26 Wave# 最近很多客戶都陸續升級到 Dynamics 365 Business Central 26 wave, Microsoft 提供一個基于Copilot 的Sales Order Agent&#xff0c;此文將此功能做個介紹. Explorer: 可以看到26版本上面增加了這樣一個新圖標。 Configuration: 配置過程…

【harbor】--配置https

使用自建的 CA 證書來自簽署和啟用 HTTPS 通信。 &#xff08;1&#xff09;生成 CA認證 使用 OpenSSL 生成一個 2048位的私鑰這是 自建 CA&#xff08;證書頒發機構&#xff09; 的私鑰&#xff0c;后續會用它來簽發證書。 # 1創建CA認證 cd 到harbor [rootlocalhost harbo…

Selenium基礎操作方法詳解

Selenium基礎操作方法詳解&#xff1a;從零開始編寫自動化腳本&#xff08;附完整代碼&#xff09; 引言 Selenium是自動化測試和網頁操作的利器&#xff0c;但對于新手來說&#xff0c;掌握基礎操作是成功的第一步。本文將手把手教你使用Selenium完成瀏覽器初始化、元素定位、…

python同步mysql數據

python寫了一個簡單的mysql數據同步腳本,只作為學習練習,大佬勿噴 # -*- coding: utf-8 -*- """ Time:2025/5/29 14:38 Auth:HEhandsome """ import pymysql from pymysql import Connectclass Mysql:def __init__(self):#源數據庫self.sou_hos…

手撕Java+硅基流動實現MCP服務器教程

手撕Java硅基流動實現MCP服務器教程 一、MCP協議核心概念 MCP是什么 MCP 是 Anthropic (Claude) 主導發布的一個開放的、通用的、有共識的協議標準。 ● MCP 是一個標準協議&#xff0c;就像給 AI 大模型裝了一個 “萬能接口”&#xff0c;讓 AI 模型能夠與不同的數據源和工…

.net consul服務注冊與發現

.NET中Consul服務注冊與發現的技術實踐 在微服務架構中&#xff0c;服務的注冊與發現是至關重要的環節&#xff0c;它能幫助各個服務之間實現高效的通信和協作。Consul作為一款功能強大的工具&#xff0c;為我們提供了優秀的服務注冊與發現解決方案。今天&#xff0c;我們就來…