摘要
策略設計模式是一種行為型設計模式,它定義了一系列算法并將每個算法封裝起來,使它們可以相互替換。該模式讓算法的變化獨立于使用算法的客戶,從而使得算法可以靈活地切換和擴展。其主要角色包括策略接口、具體策略類和環境類。策略模式的結構通過類圖和時序圖進行展示,實現方式涵蓋定義策略接口、實現具體策略類、定義環境類等步驟。它適用于多種場景,如在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
- 策略設計模式