策略模式隨筆~

在這里插入圖片描述

若感行文枯燥,請移步至文末Gitee地址中查看源碼自行測試感受策略模式之魅力。

一、策略模式的核心概念

策略模式的定義

定義算法族,封裝每個算法,使其可互換。

核心三要素

  • Context:上下文,負責接收客戶端請求并委托具體策略對象處理,實現業務邏輯與算法實現的解耦。
  • Strategy:定義接口和規范
  • ConcreteStrategy:具體的實現策略

如果把策略模式想象成一個萬能遙控器,遙控器通過不同的控制卡控制不同的設備實現不同的功能;遙控器承擔Context角色,作為控制中樞提供統一操作入口;控制卡接口插槽則是對應Strategy,定義標準功能;空調、燈光、音箱控制卡則是具體的實現策略(ConcreteStrategy),各自實現溫度調節、亮度調控、音量控制等具體功能。

本質

Java中推薦面向接口編程,而非面向實現,策略模式作為這一原則的典型應用,通過抽象策略接口與具體實現解耦,有新的擴展需求時,只需要增加其實現即可,而無需對源代碼進行改動,也符合對新增開放,對修改關閉的原則(開閉原則)。基于這種設計思想,在新增設備類型時(如加濕器控制卡),只需擴展新的策略實現而無需修改遙控器本體,即無需修改原代碼,只在原代碼的基礎上新增。

模式結構解析

將策略模式的結構應用于真實且常見的業務場景如支付場景,如在門診收費頁面,用戶可以選擇支付寶、微信、銀聯支付,不同的支付方式交互的方式不同,則需要不同的支付實現策略,那么結構參考下圖:

在這里插入圖片描述

二、解決了什么問題&應用場景

應用場景

在支付實際業務場景中,我們需要使用支持不同的支付方式如:支付寶、微信、銀聯,每種支付方式調用的接口API、請求參數、返回結果各不相同,有時系統有接入新的支付方式的需求,同時支付相關的業務邏輯比較復雜,每種支付方式的實現代碼都會比較長,尤其是聚合了多種支付方式的系統,在維護和開發時成本都更高。

解決了什么問題

策略模式解決了以下痛點:

  1. 代碼耦合高:不同支付方式實現混雜在業務邏輯中,存在大量if-else/switch分支
  2. 擴展成本高:新增支付方式需要修改原有支付邏輯,違反開閉原則
  3. 可維護性差:單個方法可能膨脹至上千行,參數傳遞混亂(如不同支付方式參數通過Map傳遞)
  4. 測試便利性: 新增策略時可以直接測試新邏輯,不影響原邏輯

代碼示例

使用偽代碼展示當業務邏輯復雜時,if、switch、策略模式各自的實現方案。

if-else
@Slf4j
@Service
public class IfPaymentServiceImpl implements IfPaymentService {@Overridepublic String pay(String type, BigDecimal amount) {if (Constant.PAYConstant.ALI_PAY.equals(type)) {return "支付寶支付成功,金額:" + amount;} else if (Constant.PAYConstant.WECHAT_PAY.equals(type)) {return "微信支付成功,金額:" + amount;} else if (Constant.PAYConstant.UNION_PAY.equals(type)) {return "銀聯支付成功,金額:" + amount;}throw new IllegalArgumentException("無效支付方式");}
}
switch-case
public class SwitchPaymentServiceImpl implements SwitchPaymentService {@Overridepublic String pay(String type, BigDecimal amount) {switch (type) {case Constant.PAYConstant.ALI_PAY:return "支付寶支付成功,金額:" + amount;case Constant.PAYConstant.WECHAT_PAY:return "微信支付成功,金額:" + amount;case Constant.PAYConstant.UNION_PAY:return "銀聯支付成功,金額:" + amount;default:throw new IllegalArgumentException("無效支付方式");}}
}
策略模式

支付方式的策略工廠,類比于使遙控器找到對應的功能的控制卡。

/*** 支付方式的策略工廠*/
@Slf4j
@Component
public class PaymentStrategyFactory {/*** 策略池*/private final Map<String, PaymentService> STRATEGY_MAP = new ConcurrentHashMap<>();@Resourceprivate List<PaymentService> strategies;/*** Spring啟動時注入所有的支付策略*/@PostConstructpublic void initStrategies() {for (PaymentService strategy : strategies) {log.info("注入策略:{}", strategy.getClass().getSimpleName());String type = strategy.getClass().getSimpleName().replace("Strategy", "");STRATEGY_MAP.put(type, strategy);}}/*** 根據上下文獲取支付策略* @param type 上下文參數* @return 支付策略*/public PaymentService getStrategy(String type) {PaymentService paymentService = STRATEGY_MAP.get(type);return Optional.ofNullable(paymentService).orElseThrow(() -> new IllegalArgumentException("無效支付類型"));}}

類比于遙控器中插槽,定義標準功能。

public interface PaymentService {/*** 支付接口*/String pay(String type, BigDecimal amount);
}

具體實現策略,指定遙控器可以控制設備的具體功能的視線方式。

@Slf4j
@Component
public class AlipayStrategy implements PaymentService {@Overridepublic String pay(String type, BigDecimal amount) {try {Thread.sleep(2000);} catch (Exception e) {log.info("異常", e);}return "支付寶支付成功,金額:" + amount;}
}

代碼地址

源碼

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

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

相關文章

Linux的目錄結構(介紹,具體目錄結構)

目錄 介紹 具體目錄結構 簡潔的目錄解釋 詳細的目錄解釋 介紹 Linux的文件系統是采用級層式的樹狀目錄結構&#xff0c;在此結構的最上層是根目錄“/”。Linux的世界中&#xff0c;一切皆文件&#xff08;比如&#xff1a;Linux會把硬件映射成文件來管理&#xff09; 具體目…

AWS CloudFront加速S3配置跨域

1、點擊分配 源我們就選擇S3–>選擇我們要加速的S3存儲桶 2、創建OAC訪問方式 在我們的來源訪問處–>來源訪問控制設置(推薦)–>選擇創建新的OAC(Create new OAC)–>自定義名字按默認選項保存–>選擇剛剛新創建的OAC 3、選擇查看器的配置 根據具體情況&#x…

進程控制(上)【Linux操作系統】

進程控制 寫時拷貝 本質是一種減少深拷貝的方法 Linux中有很多拷貝的場景都用得上寫時拷貝&#xff0c;下面以創建子進程時的寫時拷貝為例&#xff1a; 子進程被創建的時候&#xff1a; 會繼承父進程的mm_struct和頁表 所以子進程剛剛繼承時&#xff0c;父子進程的代碼和數據…

Flutter 強制橫屏

在 Flutter 中&#xff0c;可以通過設置 SystemChrome 來強制應用橫屏顯示。以下是實現這一功能的詳細步驟和代碼示例&#xff1a; 步驟 1&#xff1a;導入必要的包 確保在文件頂部導入了 services.dart 包&#xff0c;因為 SystemChrome 類位于該包中。 import package:flut…

Git完全指南:從入門到精通版本控制 ------- Git核心命令(6)

Git核心命令完全指南&#xff1a;從入門到高效協作 前言 在軟件開發領域&#xff0c;Git已成為現代版本控制的代名詞。據統計&#xff0c;全球超過90%的開發團隊使用Git進行代碼管理。然而&#xff0c;許多開發者僅停留在基礎命令的機械使用層面&#xff0c;未能真正掌握Git命…

關于Newtonsoft.Json

歷史 Newtonsoft.Json&#xff08;也稱為 Json.NET&#xff09;是由 James Newton - King 開發的一個開源的 JSON 處理庫&#xff0c;它于 2007 年首次發布。在早期&#xff0c;.NET 平臺缺乏一個強大且靈活的 JSON 處理工具&#xff0c;Newtonsoft.Json 應運而生&#xff0c;…

git reset詳解

一、git reset 的核心作用 用于 移動當前分支的 HEAD 指針 到指定的提交&#xff0c;并可選擇是否修改工作區和暫存區。 ?? 注意&#xff1a;若提交已被推送到遠程倉庫&#xff0c;強制重置&#xff08;--hard&#xff09;后需謹慎操作&#xff0c;避免影響協作。 二、三種模…

【unity游戲開發入門到精通——UGUI】CanvasScaler畫布縮放器組件

注意&#xff1a;考慮到UGUI的內容比較多&#xff0c;我將UGUI的內容分開&#xff0c;并全部整合放在【unity游戲開發——UGUI】專欄里&#xff0c;感興趣的小伙伴可以前往逐一查看學習。 文章目錄 一、CanvasScaler畫布縮放器組件是什么二、CanvasScaler的三種適配模式1、Cons…

Kubernetes控制平面組件:API Server Webhook 授權機制 詳解

云原生學習路線導航頁&#xff08;持續更新中&#xff09; kubernetes學習系列快捷鏈接 Kubernetes架構原則和對象設計&#xff08;一&#xff09;Kubernetes架構原則和對象設計&#xff08;二&#xff09;Kubernetes架構原則和對象設計&#xff08;三&#xff09;Kubernetes控…

Python自動化辦公

第五篇&#xff1a;Python自動化辦公&#xff1a;10行代碼搞定重復性工作 適合讀者&#xff1a;職場人士、數據分析師 | 閱讀時長&#xff1a;12分鐘 引言 每天重復處理Excel、PDF或郵件&#xff1f;Python可以幫你自動化這些枯燥任務&#xff0c;節省90%的時間。本文通過實際…

【3】k8s集群管理系列--包應用管理器helm之chart資源打包并推送到harbor鏡像倉庫

一、chart資源打包 helm package ./web-chart # 當前目錄會生成一個tgz的壓縮文件二、安裝help push插件&#xff08;用于推送前面打包的文件&#xff0c;到鏡像倉庫&#xff09; .1 下載help-push二進制文件 wget https://github.com/chartmuseum/helm-push/releases/down…

【SpringBoot Druid Mysql多數據源整合】

SpringBoot Druid Mysql多數據源整合 一、背景二、配置結果2.1 SpringBoot java 類配置2.1.1 啟動類配置2.1.2 java Config配置 2.2 SpringBoot yml 配置 三、mybatis插件配置3.1 PageHelper的yml配置3.2 mybatis設置自定義字段默認值 四、配置解釋 一、背景 公司項目需要連接另…

GGML源碼逐行調試(中)

目錄 前言1. 簡述2. 加載模型超參數3. 加載詞匯表4. 初始化計算上下文5. 初始化計算后端6. 創建模型張量7. 分配緩沖區8. 加載模型權重結語下載鏈接參考 前言 學習 UP 主 比飛鳥貴重的多_HKL 的 GGML源碼逐行調試 視頻&#xff0c;記錄下個人學習筆記&#xff0c;僅供自己參考&…

kubectl的使用

查看集群有多少節點 kubectl get nodes 獲取集群狀態的摘要信息&#xff08;組件信息&#xff09; kubectl get cs 查看所有命名空間下的所有pod的狀態和信息 kubectl get pods --all-namespaces 查看所有命名空間的狀態和信息 kubectl get namespaces /ns 查看kube-system…

git在分支上會退到某個指定的commit

1、在idea上先備份好分支&#xff08;基于現有分支new branch&#xff09; 2、在gitlab管理端刪除現有分支 3、在idea中大卡terminal&#xff0c;執行 git log 查看commit log ,找到要會退到的commit唯一碼&#xff0c;然后執行git reset 唯一碼 4、查看本地代碼狀態 git st…

動態路由, RIP路由協議,RIPv1,RIPv2

動態路由 1、回顧 路由&#xff1a;從源主機到目標主機的過程 源主機發送數據給目標主機&#xff0c;源主機會查看自身的路由信息 如果目標主機是自己同網段&#xff0c;源主機查看的是直連路由 如果目標主機和自己不同網段&#xff0c;源主機查看的是靜態路由、動態路由、默…

前端面試-工程化(webpack、vite)

Webpack 相關問題&#xff08;25道&#xff09; Webpack 的核心概念有哪些&#xff1f;&#xff08;Entry、Output、Loader、Plugin、Module、Bundle&#xff09;如何配置 Webpack 的多入口和多出口&#xff1f;Webpack 的 Tree Shaking 實現原理是什么&#xff1f;Loader 和 …

idea 2024 build菜單不見了

Q如題 idea 2024 新版UI添加build和recompile菜單 A如圖&#xff0c;右鍵頂部欄之后&#xff0c;點擊Add to Main Toolbar菜單&#xff0c;在里面就能找到Build菜單&#xff0c;添加接口。 Recompile菜單的話在Customize Toolbar中搜索添加才行。

【開源項目】Excel手撕AI算法深入理解(三):時序(RNN、mamba)

項目源碼地址&#xff1a;https://github.com/ImagineAILab/ai-by-hand-excel.git 一、RNN 1. RNN 的核心思想 RNN 的設計初衷是處理序列數據&#xff08;如時間序列、文本、語音&#xff09;&#xff0c;其核心特點是&#xff1a; 隱藏狀態&#xff08;Hidden State&#xff…

pycharm已有python3.7,如何新增Run Configurations中的Python interpreter為python 3.9

在 PyCharm 中&#xff0c;如果你已經安裝了 Python 3.9&#xff0c;并且希望在 Run Configurations 中新增一個 Python 3.9 的解釋器&#xff0c;可以按照以下步驟操作&#xff1a; 步驟 1&#xff1a;打開 PyCharm 設置 點擊 PyCharm 左上角的 File 菜單。選擇 Settings&am…