設計模式:策略模式 - 消除復雜條件判斷的利器

一、什么是策略模式?

策略模式(Strategy Pattern)是一種行為型設計模式,它將一組算法或業務邏輯封裝為獨立的策略類,使這些策略可以互換使用,并通過上下文類動態選擇合適的策略。

核心思想

? 將不同的行為或算法獨立封裝為策略類,客戶端無需關注內部實現邏輯。

? 遵循開閉原則(OCP),新增策略時無需修改已有代碼,避免復雜的if-else判斷邏輯。

策略模式的關鍵結構

1.策略接口(Strategy)

定義一組算法的通用接口。

2.具體策略(Concrete Strategy)

每個具體策略實現不同的算法。

3上下文類(Context)

上下文類持有策略接口的引用,用于調用具體策略。

二、策略模式的實際案例

場景:訂單支付系統(支持支付寶、微信和銀聯支付)。

直接實現(未使用策略模式):

public class PaymentService {public void pay(String paymentType, double amount) {// 支付寶支付if ("ALIPAY".equals(paymentType)) {System.out.println("Using Alipay to pay: " + amount);// 微信支付} else if ("WECHAT".equals(paymentType)) {System.out.println("Using WeChat Pay to pay: " + amount);// 銀聯支付 } else if ("UNIONPAY".equals(paymentType)) {System.out.println("Using UnionPay to pay: " + amount);} else {System.out.println("Unsupported payment type!");}}
}

問題分析

1.違反開閉原則:每新增一種支付方式,都需要修改pay()方法,代碼難以維護。

2.可讀性和擴展性差:復雜條件判斷導致代碼臃腫,增加閱讀和測試成本。

3.高耦合性:支付邏輯直接耦合在調用代碼中,難以重用和擴展。

使用策略模式實現

1.定義支付策略接口

策略模式的第一步是定義一個接口,抽象出所有支付方式的共同行為。

/*** 支付策略接口,所有支付方式必須實現該接口。*/
public interface PaymentStrategy {/*** 執行支付操作* @param amount 支付金額*/void pay(double amount);
}

2.實現具體的支付策略類

每個支付方式對應一個實現類,獨立封裝具體的支付邏輯。

/*** 支付寶支付策略*/
public class AlipayStrategy implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("使用支付寶支付了 " + amount + " 元");}
}/*** 微信支付策略*/
public class WeChatPayStrategy implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("使用微信支付了 " + amount + " 元");}
}/*** 銀聯支付策略*/
public class UnionPayStrategy implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("使用銀聯支付了 " + amount + " 元");}
}

3.定義支付上下文類

上下文類負責持有具體的策略對象,并在需要時調用對應的支付邏輯。

/*** 支付上下文類,用于管理支付策略*/
public class PaymentContext {// 策略對象private PaymentStrategy paymentStrategy;/*** 構造方法,初始化支付策略*/public PaymentContext(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}/*** 執行支付操作* @param amount 支付金額*/public void executePayment(double amount) {paymentStrategy.pay(amount);}
}

4.客戶端代碼:選擇支付方式并支付

客戶端通過選擇不同的策略,實現不同的支付方式。

/*** 客戶端測試代碼*/
public class Client {public static void main(String[] args) {double amount = 200.0; // 支付金額// 使用支付寶支付PaymentContext context = new PaymentContext(new AlipayStrategy());context.executePayment(amount);// 使用微信支付context = new PaymentContext(new WeChatPayStrategy());context.executePayment(amount);// 使用銀聯支付context = new PaymentContext(new UnionPayStrategy());context.executePayment(amount);}
}

運行結果:

使用支付寶支付了 200.0 元
使用微信支付了 200.0 元
使用銀聯支付了 200.0

代碼結構說明

1.策略接口PaymentStrategy

定義支付方法pay(),所有支付類須實現它。

2.具體策略類

AlipayStrategy:實現支付寶支付邏輯。

WeChatPayStrategy:微信支付邏輯。

UnionPayStrategy:實現銀聯支付邏輯。

3.上下文類PaymentContext

維護一個策略對象,客戶端可以動態選擇不同的支付策略。

4.客戶端

通過創建不同的支付策略對象,實現靈活的支付功能。

三、策略模式的價值

1.簡化主邏輯,消除復雜條件判斷

策略模式將復雜的if-else或switch-case語句分解為獨立的策略類,使主邏輯更專注于調用流程(上下文),代碼清晰且易維護。

2.便于擴展,符合開閉原則

新增功能(如支付方式)時,只需新增策略類,無需修改現有代碼,既減少對穩定模塊的干擾,也降低擴展成本。

3.提升復用性

策略類通過模塊化設計,將具體邏輯與選擇邏輯分離,可直接復用于其他系統。

四、適用場景

1.動態行為選擇

系統需要在運行時根據不同條件選擇不同的行為或算法,例如支付方式切換、促銷規則變化、日志格式化樣式調整等。

2.簡化條件分支

當代碼中存在大量if-else或switch-case時,且未來可能增加判斷分支時,可通過策略模式優化為獨立的策略類,提升可維護性。

3.高擴展性需求

系統需要頻繁新增功能,但不希望頻繁修改現有代碼,策略模式符合開閉原則(OCP)。

4.測試驅動開發場景

需要對不同行為進行獨立驗證時,策略模式將這些行為解耦,便于單獨測試。

五、總結

策略模式通過將行為或算法封裝為獨立類,結合上下文動態選擇策略,提升了系統的靈活性、擴展性與可維護性。

核心價值

? 開發上,簡化主邏輯,消除復雜條件判斷,增強擴展性與復用性。

? 測試上,降低模塊間耦合性,簡化單元測試,降低回歸測試成本。

1.策略類過多可能導致類數量膨脹,應合理設計。

2.在簡單場景下,策略模式可能顯得“過度設計”,需權衡實際需求。

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

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

相關文章

LeetCode hot 100—不同路徑

題目 一個機器人位于一個 m x n 網格的左上角 (起始點在下圖中標記為 “Start” )。 機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為 “Finish” )。 問總共有多少條不同的路徑? …

pytorch查詢字典、列表維度

輸出tensor變量維度 print(a.shape)輸出字典維度 for key, value in output_dict.items():if isinstance(value, torch.Tensor):print(f"{key} shape:", value.shape)輸出列表維度 def get_list_dimensions(lst):# 基線條件:如果lst不是列表&#xff0…

多坐標系變換全解析:從相機到WGS-84的空間坐標系詳解

多坐標系變換全解析:從相機到WGS-84的空間坐標系詳解 一、常見坐標系簡介二、各坐標系的功能和使用場景1. WGS-84 大地坐標系(經緯高)2. 地心直角坐標系(ECEF)3. 本地 ENU / NED 坐標系4. 平臺坐標系(Body)5. 相機坐標系三、坐標變換流程圖四、如何選用合適的坐標系?五…

【NumPy科學計算:高性能數組操作核心指南】

目錄 前言:技術背景與價值當前技術痛點解決方案概述目標讀者說明 一、技術原理剖析核心概念圖解關鍵技術模塊技術選型對比 二、實戰演示環境配置要求核心代碼實現運行結果驗證 三、性能對比測試方法論量化數據對比結果分析 四、最佳實踐推薦方案 ?常見錯誤 ?調試技…

【特權FPGA】之PS/2鍵盤解碼

0 故事背景 見過這種接口的朋友們,大概都已經成家立業了吧。不過今天我們不討論這種接口的歷史,只講講這種接口的設計。(如果還沒有成家的朋友也別生氣,做自己想做的事情就對了!) 1 時序分析 數據幀格式如圖…

DAPP實戰篇:使用web3.js實現前端輸入錢包地址查詢該地址的USDT余額—操作篇

專欄:區塊鏈入門到放棄查看目錄-CSDN博客文章瀏覽閱讀396次。為了方便查看將本專欄的所有內容列出目錄,按照順序查看即可。后續也會在此規劃一下后續內容,因此如果遇到不能點擊的,代表還沒有更新。聲明:文中所出觀點大多數源于筆者多年開發經驗所總結,如果你想要知道區塊…

高中生學習數據隱私保護的“技術-制度-文化”協同機制研究

一、引言 1.1 研究背景與意義 在數字化時代的浪潮下,教育領域正經歷著深刻的變革,智能教育平臺如雨后春筍般涌現,為高中教育帶來了新的活力與機遇。這些平臺借助先進的信息技術,能夠實時收集、分析大量的高中生學習數據&#xf…

【Java多線程】告別線程混亂!深度解析Java多線程4大實現方式(附實戰案例)

一、繼承Thread類 實現步驟&#xff1a; 1.繼承Thread類 2.重寫run()方法 3.創建線程對象并調用start()方法 示例&#xff1a; class MyThread extends Thread {Overridepublic void run() {for (int i 0; i < 5; i) {System.out.println(Thread.currentThread().getNam…

全國產V7-690T核心板/算法驗證板/FPGA開發板

UD SOM-404全國產化信號處理模塊既可以作為核心板使用&#xff0c;也可以單獨使用。FPGA對外有80組GTY通過兩個FMC連接器全部引出&#xff0c;多個模塊可以級聯使用&#xff0c;擴展信號處理能力。FMC連接器也滿足標準規范&#xff0c;可以插入標準的FMC或FMC子板。模塊為100%國…

STM32_HAL庫提高中斷執行效率

目錄 中斷流程分析我的解決辦法優缺點 大家都在說STM32 HAL 庫中斷效率低下。具體哪里不行&#xff1f;如何優化&#xff1f; 我手里的項目要用到多個定時器TIM6、TIM7、TIM9、TIM10、TIM11、TIM12、TIM13&#xff0c;在處理這些定時器中斷的時候&#xff0c;也發現了這個問題。…

RabbitMQ惰性隊列的工作原理、消息持久化機制、同步刷盤的概念、延遲插件的使用方法

惰性隊列工作原理 惰性隊列通過盡可能多地將消息存儲到磁盤上來減少內存的使用。與傳統隊列相比&#xff0c;惰性隊列不會主動將消息加載到內存中&#xff0c;而是盡量讓消息停留在磁盤上&#xff0c;從而降低內存占用。盡管如此&#xff0c;它并不保證所有操作都是同步寫入磁…

Spark Core(二)

Spark-Core編程&#xff08;二&#xff09; RDD轉換算子 RDD 根據數據處理方式的不同將算子整體上分為 Value 類型、雙 Value 類型和 Key-Value 類型 Value類型 1&#xff09;map 將處理的數據逐條進行映射轉換&#xff0c;這里的轉換可以是類型的轉換&#xff0c;也可以是…

C#打開文件及目錄腳本

如果每天開始工作前都要做一些準備工作&#xff0c;比如打開文件或文件夾&#xff0c;我們可以使用代碼一鍵完成。 using System.Diagnostics; using System.IO;namespace OpenFile {internal class Program{static void Main(string[] args){Console.WriteLine("Hello, …

Python生成exe

其中的 -w 參數是 PyInstaller 用于窗口模式&#xff08;Windowed mode&#xff09;&#xff0c;它會關閉命令行窗口的輸出&#xff0c;這通常用于 圖形界面程序&#xff08;GUI&#xff09;&#xff0c;比如使用 PyQt6, Tkinter, PySide6 等。 所以&#xff1a; 如果你在沒有…

【大模型微調】如何解決llamaFactory微調效果與vllm部署效果不一致如何解決

以下個人沒整理太全 一、生成式語言模型的對話模板介紹 使用Qwen/Qwen1.5-0.5B-Chat訓練 對話模板不一樣。回答的內容就會不一樣。 我們可以看到例如qwen模型的tokenizer_config.json文件&#xff0c;就可以看到對話模板&#xff0c;一般同系列的模型&#xff0c;模板基本都…

Linux網絡編程——詳解網絡層IP協議、網段劃分、路由

目錄 一、前言 二、IP協議的認識 1、什么是IP協議&#xff1f; 2、IP協議報頭 三、網段劃分 1、初步認識IP與路由 2、IP地址 I、DHCP動態主機配置協議 3、IP地址的劃分 I、CIDR設計 II、子網數目的計算 III、子網掩碼的確定 四、特殊的IP地址 五、IP地址的數量限…

ansible+docker+docker-compose快速部署4節點高可用minio集群

目錄 github項目地址 示例服務器列表 安裝前 修改變量文件group_vars/all.yml 修改ansible主機清單 修改setup.sh安裝腳本 用法演示 安裝后驗證 github項目地址 https://github.com/sulibao/ansible_minio_cluster.git 示例服務器列表 安裝前 修改變量文件group_var…

MySql主從相關概念

想象一下&#xff0c;你的業務飛速增長&#xff0c;用戶請求如潮水般涌來&#xff0c;突然數據庫主庫宕機&#xff0c;數據丟失&#xff0c;服務癱瘓——這簡直是開發者的噩夢&#xff01;MySQL主從復制就像一張安全網&#xff0c;通過主庫寫、從庫讀的協作模式&#xff0c;不僅…

機械臂只有位置信息是否可以進行手眼標定?

平常我在做手眼標定時&#xff0c;一般都是通過OpenCV的cv::calibrateHandEye函數進行求解&#xff0c;需要輸入多組不同的機械臂位姿。今天遇到了一款舵機機器人&#xff0c;只能獲取位置&#xff0c;得不到姿態信息&#xff0c;想著那就把姿態都設為0&#xff0c;結果求不出來…

華為數字芯片機考2025合集2已校正

單選 1. 題目內容 關于亞穩態的描述錯誤的是&#xff08; &#xff09;。 1. 解題步驟 1.1 理解亞穩態&#xff08;Metastability&#xff09;的核心特性 亞穩態是指觸發器無法在指定時間內穩定輸出有效邏輯電平&#xff08;0或1&#xff09;的狀態&#xff0c;其關鍵特點…