策略模式_行為型_GOF23


策略模式

策略模式(Strategy Pattern)是一種行為型設計模式,核心思想是將一組算法封裝成獨立對象,使它們可以相互替換,從而讓算法的變化獨立于使用它的客戶端。這類似于游戲中的技能切換——玩家根據戰況選擇不同技能(火球術、冰箭術),而角色的攻擊邏輯無需修改。


一、通俗理解

以商場促銷為例:

  1. 傳統方式:用 if-else 判斷促銷類型(滿減、折扣、積分),導致代碼臃腫且難以擴展新促銷策略。
  2. 策略模式
    • 促銷策略接口:定義統一的優惠計算接口(如 calculate())。
    • 具體策略類:滿減策略、折扣策略等各自實現算法。
    • 訂單上下文:持有當前策略對象,調用時動態執行對應算法。
      當新增“雙倍積分”促銷時,只需添加新策略類,無需修改現有代碼。

二、模式結構
  1. 抽象策略(Strategy):定義算法的公共接口(如 execute())。
  2. 具體策略(ConcreteStrategy):實現具體算法(如加法、折扣)。
  3. 上下文(Context):維護策略對象引用,提供切換和執行接口。

三、適用場景
  1. 動態算法切換:如支付方式(微信、支付寶)、排序算法(快排、歸并)。
  2. 消除條件分支:替代大量 if-elseswitch-case 語句。
  3. 算法復用與擴展:需要獨立管理多種算法變體時。

四、優缺點分析
優點缺點
1. 靈活擴展:新增策略無需修改上下文1. 類數量膨脹:每個策略需獨立類
2. 消除條件判斷:代碼更簡潔易維護2. 客戶端需感知策略存在
3. 符合開閉原則:算法與使用解耦3. 性能開銷:頻繁切換可能影響效率

五、代碼實現
1. C++ 示例(計算器策略)
#include <iostream>  // 抽象策略:運算接口  
class Strategy {  
public:  virtual int execute(int a, int b) = 0;  virtual ~Strategy() = default;  
};  // 具體策略:加法  
class AddStrategy : public Strategy {  
public:  int execute(int a, int b) override {  return a + b;  }  
};  // 上下文:計算器  
class Calculator {  Strategy* strategy;  
public:  void setStrategy(Strategy* s) { strategy = s; }  int calculate(int a, int b) {  return strategy->execute(a, b);  }  
};  int main() {  Calculator calc;  calc.setStrategy(new AddStrategy());  std::cout << "10 + 5 = " << calc.calculate(10, 5) << std::endl;  // 輸出15  // 切換策略示例:calc.setStrategy(new SubtractStrategy());  return 0;  
}  

解析

  • 通過 setStrategy() 動態更換加減乘除算法。

2. Python 示例(促銷策略)
from abc import ABC, abstractmethod  class PromotionStrategy(ABC):  @abstractmethod  def calculate(self, price: float) -> float:  pass  class FullReductionStrategy(PromotionStrategy):  # 滿減策略  def calculate(self, price):  return price - 20 if price >= 100 else price  class DiscountStrategy(PromotionStrategy):       # 折扣策略  def calculate(self, price):  return price * 0.8  class Order:  def __init__(self, strategy: PromotionStrategy):  self.strategy = strategy  def checkout(self, price):  return self.strategy.calculate(price)  # 客戶端  
order = Order(FullReductionStrategy())  
print(f"滿減后價格:{order.checkout(150)}")  # 輸出130.0  

特點

  • Python支持鴨子類型,無需嚴格接口繼承。

3. Java 示例(支付策略 + 工廠模式)
// 策略接口  
interface PaymentStrategy {  void pay(double amount);  
}  // 具體策略:微信支付  
class WechatPay implements PaymentStrategy {  public void pay(double amount) {  System.out.printf("微信支付:%.2f元\n", amount);  }  
}  // 策略工廠(管理實例)  
class PaymentFactory {  private static final Map<String, PaymentStrategy> strategies = new HashMap<>();  static {  strategies.put("wechat", new WechatPay());  strategies.put("alipay", new Alipay());  }  public static PaymentStrategy getStrategy(String key) {  return strategies.getOrDefault(key, new DefaultPay());  }  
}  // 上下文  
class ShoppingCart {  private PaymentStrategy strategy;  public void setStrategy(String key) {  this.strategy = PaymentFactory.getStrategy(key);  }  public void checkout(double amount) {  strategy.pay(amount);  }  
}  // 測試  
ShoppingCart cart = new ShoppingCart();  
cart.setStrategy("wechat");  
cart.checkout(99.9);  // 輸出:微信支付:99.90元  

優化點

  • 工廠模式集中管理策略實例,避免重復創建。

六、總結與擴展

策略模式通過算法封裝動態切換實現了高擴展性,特別適合以下場景:

  1. 電商促銷:不同優惠規則獨立管理。
  2. 游戲技能系統:角色動態切換攻擊策略。
  3. 數據解析:支持JSON、XML等多種格式解析器。

擴展技巧

  • 結合享元模式復用無狀態策略對象(如線程安全的計算策略)。
  • 使用Lambda表達式(Java/Python)簡化小型策略類的定義。
參考資料
策略模式基礎結構與角色定義
三國錦囊案例與設計思想
C++策略模式與對象生命周期管理
Python策略模式與動態語言特性
Java策略模式與線程安全實踐

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

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

相關文章

【Python】天氣數據可視化

1. Python進行數據可視化 在數據分析和科學計算領域&#xff0c;Python憑借其強大的庫和簡潔的語法&#xff0c;成為了眾多開發者和科研人員的首選工具。數據可視化作為數據分析的重要環節&#xff0c;能夠幫助我們更直觀地理解數據背后的規律和趨勢。本文將詳細介紹如何使用P…

深度學習4.4筆記

《動手學深度學習》-4.4-筆記 驗證數據集&#xff1a;通常是從訓練集中劃分出來的一部分數據&#xff0c;不要和訓練數據混在一起&#xff0c;評估模型好壞的數據集 測試數據集&#xff1a;只用一次的數據集 k-折交叉驗證&#xff08;k-Fold Cross-Validation&#xff09;是…

vue 兩種路由模式

一、兩種模式比較 在vue.js中&#xff0c;路由模式分為兩種&#xff1a;hash 模式和 history 模式。這兩種模式決定了URL的結構和瀏覽器歷史記錄的管理方式。 1. hash 模式帶 #&#xff0c;#后面的地址變化不會引起頁面的刷新。換句話說&#xff0c;hash模式不會將#后面的地址…

Android生態大變革,谷歌調整開源政策,核心開發不再公開

“開源”這個詞曾經是Android的護城河&#xff0c;如今卻成了谷歌的燙手山芋。最近谷歌宣布調整Android的開源政策&#xff0c;核心開發將全面轉向私有分支。翻譯成人話就是&#xff1a;以后Android的核心更新&#xff0c;不再公開共享了。 這操作不就是開源變節嗎&#xff0c;…

JavaScript中集合常用操作方法詳解

JavaScript中集合常用操作方法詳解 JavaScript中的集合主要包括數組(Array)、集合(Set)和映射(Map)。下面我將詳細介紹這些集合類型的常用操作方法。 數組(Array) 數組是JavaScript中最常用的集合類型&#xff0c;提供了豐富的操作方法。 創建數組 // 字面量創建 const ar…

【HC-05】藍牙串口通信模塊調試與應用(1)

一、HC-05 基礎學習視頻 HC-05藍牙串口通信模塊調試與應用1 二、HC-05學習視頻課件

【學Rust寫CAD】18 定點數2D仿射變換矩陣結構體(MatrixFixedPoint結構別名)

源碼 // matrix/fixed.rs use crate::fixed::Fixed; use super::generic::Matrix;/// 定點數矩陣類型別名 pub type MatrixFixedPoint Matrix<Fixed, Fixed, Fixed, Fixed, Fixed, Fixed>;代碼解析 這段代碼定義了一個定點數矩陣的類型別名 MatrixFixedPoint&#xff…

axios文件下載使用后端傳遞的名稱

java后端通過HttpServletResponse 返回文件流 在Content-Disposition中插入文件名 一定要設置Access-Control-Expose-Headers&#xff0c;代表跨域該Content-Disposition返回Header可讀&#xff0c;如果沒有&#xff0c;前端是取不到Content-Disposition的&#xff0c;可以在統…

HarmonyOS之深入解析如何根據url下載pdf文件并且在本地顯示和預覽

一、文件下載 ① 網絡請求配置 下載在線文件&#xff0c;需要訪問網絡&#xff0c;因此需要在 config.json 中添加網絡權限&#xff1a; {"module": {"requestPermissions": [{"name": "ohos.permission.INTERNET","reason&qu…

鴻蒙前后端項目源碼-點餐v3.0-原創!原創!原創!

鴻蒙前后端點餐項目源碼含文檔ArkTS語言. 原創作品.我半個月寫的原創作品&#xff0c;請尊重原創。 原創作品&#xff0c;盜版必究&#xff01;&#xff01;&#xff01;&#xff01; 原創作品&#xff0c;盜版必究&#xff01;&#xff01;&#xff01;&#xff01; 原創作…

VUE3+TypeScript項目,使用html2Canvas+jspdf生成PDF并實現--分頁--頁眉--頁尾

使用html2CanvasJsPDF生成pdf&#xff0c;并實現分頁添加頁眉頁尾 1.封裝方法htmlToPdfPage.ts /**path: src/utils/htmlToPdfPage.tsname: 導出頁面為PDF格式 并添加頁眉頁尾 **/ /*** 封裝思路* 1.將頁面根據A4大小分隔邊距&#xff0c;避免內容被中間截斷* 所有元素層級不要…

5.Excel:從網上獲取數據

一 用 Excel 數據選項卡獲取數據的方法 連接。 二 要求獲取實時數據 每1分鐘自動更新數據。 A股市場_同花順行情中心_同花順財經網 用上面方法將數據加載進工作表中。 在表格內任意區域右鍵&#xff0c;刷新。 自動刷新&#xff1a; 三 缺點 Excel 只能爬取網頁上表格類型的…

《深度剖析SQL之WHERE子句:數據過濾的藝術》

在當今數據驅動的時代&#xff0c;數據處理和分析能力已成為職場中至關重要的技能。SQL作為一種強大的結構化查詢語言&#xff0c;在數據管理和分析領域占據著核心地位。而WHERE子句&#xff0c;作為SQL中用于數據過濾的關鍵組件&#xff0c;就像是一把精準的手術刀&#xff0c…

華為eNSP-配置靜態路由與靜態路由備份

一、靜態路由介紹 靜態路由是指用戶或網絡管理員手工配置的路由信息。當網絡拓撲結構或者鏈路狀態發生改變時&#xff0c;需要網絡管理人員手工修改靜態路由信息。相比于動態路由協議&#xff0c;靜態路由無需頻繁地交換各自的路由表&#xff0c;配置簡單&#xff0c;比較適合…

Docker 快速入門指南

Docker 快速入門指南 1. Docker 常用指令 Docker 是一個輕量級的容器化平臺&#xff0c;可以幫助開發者快速構建、測試和部署應用程序。以下是一些常用的 Docker 命令。 1.1 鏡像管理 # 搜索鏡像 docker search <image_name># 拉取鏡像 docker pull <image_name>…

基礎認證-單選題(一)

單選題 1、下列關于request方法和requestlnStream方法說法錯誤的是(C) A 都支持取消訂閱響應事件 B 都支持訂閱HTTP響應頭事件 C 都支持HttpResponse返回值類型 D 都支持傳入URL地址和相關配置項 2、如需修改Text組件文本的透明度可通過以下哪個屬性方法進行修改 (C) A dec…

Logback使用和常用配置

Logback 是 Spring Boot 默認集成的日志框架&#xff0c;相比 Log4j&#xff0c;它性能更高、配置更靈活&#xff0c;并且天然支持 Spring Profile 多環境配置。以下是詳細配置步驟及常用配置示例。 一、添加依賴&#xff08;非 Spring Boot 項目&#xff09; 若項目未使用 Sp…

MySQL基礎語法DDLDML

目錄 #1.創建和刪除數據庫 ?#2.如果有lyt就刪除,沒有則創建一個新的lyt #3.切換到lyt數據庫下 #4.創建數據表并設置列及其屬性,name是關鍵詞要用name包圍 ?編輯 #5.刪除數據表 #5.查看創建的student表 #6.向student表中添加數據,數據要與列名一一對應 #7.查詢studen…

在windows下安裝windows+Ubuntu16.04雙系統(下)

這篇文章的內容主要來源于這篇文章&#xff0c;為正式安裝windowsUbuntu16.04雙系統部分。在正式安裝前&#xff0c;若還沒有進行前期準備工作&#xff08;1.分區2.制作啟動u盤&#xff09;&#xff0c;見《在windows下安裝windowsUbuntu16.04雙系統(上)》 二、正式安裝Ubuntu …

Ubuntu24.04 離線安裝 MySQL8.0.41

一、環境準備 1.1 官方下載MySQL8.0.41 完整包 1.2 上傳包 & 解壓 上傳包名稱是&#xff1a;mysql-server_8.0.41-1ubuntu24.04_amd64.deb-bundle.tar # 切換到上傳目錄 cd /home/MySQL8 # 解壓&#xff1a; tar -xvf mysql-server_8.0.41-1ubuntu24.04_amd64.deb-bundl…