java 設計模式之策略模式

簡介

策略模式:策略模式可以定制目標對象的行為,它通過傳入不同的策略實現,來配置目標對象的行為。使用策略模式,就是為了定制目標對象在某個關鍵點的行為。

策略模式中的角色:

  • 上下文類:持有一個策略類的引用,最終給客戶端調用
  • 策略接口:定義規范,所有的策略類都要實現
  • 具體策略累:實現具體算法

優缺點:

  • 優點:
    • 避免多重if else語句
    • 策略類之間可以自由切換;
    • 增加一個新的策略只需要添加一個具體的策略類即可;
  • 缺點:客戶端必須知道所有的策略類,并自行決定使用哪一個策略類

策略模式的實現

案例:售貨員和優惠策略,用戶可以配置售貨員使用的優惠策略

第一步:上下文類

public class SaleMan {// 上下文類持有策略接口的實例,用戶通過傳入策略接口的不同實現,來配置上下文類的行為private final Strategy strategy;public SaleMan() { }public SaleMan(Strategy strategy) {this.strategy = strategy;}public void saleManShow() {System.out.print("售貨員促銷商品時使用的優惠策略:");strategy.show();}
}

第二步:策略接口

public interface Strategy {void show();
}

第三步:具體的策略類

// 策略1
public class StrategyA implements Strategy {@Overridepublic void show() {System.out.println("買一送一");}
}// 策略2
public class StrategyB implements Strategy{@Overridepublic void show() {System.out.println("滿200減50");}
}// 策略3
public class StrategyC implements Strategy{@Overridepublic void show() {System.out.println("滿1000減200");}
}

測試:

public class Client {public static void main(String[] args) {SaleMan saleMan = new SaleMan(new StrategyA());saleMan.saleManShow();}
}

總結:在這個案例中,用戶在創建售貨員實例時,可以配置售貨員使用的優惠策略

策略模式本質上就是把上下文類中的某個關鍵流程提取出來,抽象出接口和實現類,接口就是關鍵流程要做什么,實現類就是關鍵流程的不同實現。如果不使用策略模式,這些策略都要放到上下文類中,那么用戶需要傳入參數來指定走哪條鏈路,這會導致大量的if else。策略模式可以讓目標類更簡潔。

使用案例

jdk源碼案例:線程池的拒絕策略

1、上下文類

public class ThreadPoolExecutor extends AbstractExecutorService {// 1、上下文類持有策略接口的實例// 拒絕策略private volatile RejectedExecutionHandler handler;// 2、用戶通過構造方法來指定上下文類使用哪個拒絕策略public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {  // 拒絕策略// 這里省略了大量代碼,重點關注,外部傳入策略接口的實例,來指定線程池在無法// 執行任務時該怎么做this.handler = handler;}// 3、拒絕策略在上下文類中的執行。線程池執行任務的機制public void execute(Runnable command) {if (command == null)throw new NullPointerException();int c = ctl.get();if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command))reject(command);  else if (workerCountOf(recheck) == 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);  // 重點看這里,如果無法執行任務,就執行拒絕策略}// 執行拒絕策略final void reject(Runnable command) {handler.rejectedExecution(command, this);}
}

2、策略接口

public interface RejectedExecutionHandler {// 策略方法,任務無法執行時線程池該怎么辦void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

3、具體的策略實現

// 策略1:拋異常,這是默認的拒絕策略
public static class AbortPolicy implements RejectedExecutionHandler {public AbortPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {// 拋異常throw new RejectedExecutionException("Task " + r.toString() +" rejected from " +e.toString());}
}// 策略2:如果線程池沒有關閉,由調用者來執行任務
public static class CallerRunsPolicy implements RejectedExecutionHandler {public CallerRunsPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {if (!e.isShutdown()) {r.run();}}
}// 策略3:如果線程池沒有關閉,丟棄隊列中最老的任務
public static class DiscardOldestPolicy implements RejectedExecutionHandler {public DiscardOldestPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {if (!e.isShutdown()) {e.getQueue().poll();  // 阻塞隊列的頭結點出隊e.execute(r);         // 執行當前異步任務}}
}// 策略4:丟失任務,靜默,不拋異常
public static class DiscardPolicy implements RejectedExecutionHandler {public DiscardPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {}
}

在學習線程池時,需要了解線程池的拒絕策略,并且選擇一個合適的拒絕策略,這里就是原因,使用了策略模式,用戶需要了解所有策略,并且指定使用哪種策略。

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

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

相關文章

Perf學習

重要的能解決的問題是這些&#xff1a; perf_events is an event-oriented observability tool, which can help you solve advanced performance and troubleshooting functions. Questions that can be answered include: Why is the kernel on-CPU so much? What code-pa…

「倉頡編程語言」Demo

倉頡編程語言」Demo python 1)# 倉頡語言寫字樓管理系統示例&#xff08;虛構語法&#xff09;# 語法規則&#xff1a;中文關鍵詞 類Python邏輯定義 寫字樓管理系統屬性:租戶庫 列表.新建()報修隊列 列表.新建()費用單價 5 # 元/平方米方法 添加租戶(名稱, 樓層, 面積):…

鎖(Mutex)、信號量(Semaphore)與條件量(Condition Variable)

一、同步機制的核心意義 在多線程/多進程編程中&#xff0c;當多個執行流共享資源&#xff08;如變量、內存、文件&#xff09;時&#xff0c;可能因操作順序不確定導致數據競爭&#xff08;Data Race&#xff09;。同步機制的作用是&#xff1a; 保證原子性&#xff1a;確保…

前端基礎之《Vue(6)—組件基礎(2)》

接上一篇。 七、v-model深入學習 <html> <head><title>組件基礎-4</title><style>.score {display: inline-block;}.score>span {display: inline-block;width: 25px;height: 25px;background: url(./assets/star.png) center center / 25p…

SQL:聚合函數(Aggregate Functions)

目錄 第一性原理出發思考 ——我們為什么需要聚合函數&#xff1f; 什么是聚合函數&#xff1f; 常見聚合函數 實例講解 &#x1f538; 1. COUNT() —— 計數 &#x1f538; 2. MAX() / MIN() —— 最大 / 最小值 &#x1f538; 3. SUM() —— 求和 &#x1f538; 4. …

海關總署廣東:廣東外貿一季度進出口2.14萬億元 同期增長4.2%

大灣區經濟網灣區財經報道&#xff0c;據海關總署廣東分署統計&#xff0c;今年一季度&#xff0c;廣東外貿進出口2.14萬億元&#xff0c;較去年同期&#xff08;下同&#xff09;增長4.2%&#xff0c;增速高于全國2.9個百分點。其中&#xff0c;出口1.34萬億元&#xff0c;增長…

MySQL中高級語法

Mysql高級語法 持續更新中… 1、EXISTS語法 一、基本語法結構 SELECT [列名] FROM [主表] WHERE [條件]AND EXISTS (SELECT 1 -- 子查詢內容無關&#xff0c;僅需占位符&#xff08;如1、*、X等&#xff09;FROM [子查詢表]WHERE [關聯條件] -- 必須與外層查詢關聯&#xf…

SpringBoot 調用deepseek

個人學習心得&#xff0c;僅供參考 軟件環境&#xff1a; JDK 17 你用JDK 11 無法支持SpringBoot 3SpringBoot 3 版本以上才支持spring aimavan 3.6.11.獲取Deepseek官網的API-key 官網&#xff1a;https://platform.deepseek.com/api_keys 2.創建項目 這樣創建 添加依賴…

性能測試面試題的詳細解答

以下是性能測試面試題的詳細解答&#xff1a; 1. 性能測試的流程是怎樣的&#xff1f; 性能測試流程通常包括以下幾個步驟&#xff1a; - **需求分析**&#xff1a;明確測試目標、性能指標&#xff08;如響應時間、吞吐量等&#xff09;。 - **環境搭建**&#xff1a;搭建測試環…

C++程序設計基礎實驗:C++對C的擴展特性與應用

C程序設計基礎實驗&#xff1a;C對C的擴展特性與應用 &#x1f525; 本文詳細講解C基礎實驗&#xff0c;包含C對C語言的擴充與增強特性&#xff0c;從零開始掌握函數重載、引用、指針等核心概念&#xff0c;附詳細代碼分析與運行結果。適合C初學者和有C語言基礎想學習C的同學&a…

量子神經網絡編譯器開發指南:從理論突破到產業落地全景解析

本文深度剖析IBM Qiskit 5.0量子經典混合編譯器的技術架構&#xff0c;詳解如何基于含噪量子處理器實現MNIST手寫數字分類任務&#xff08;準確率達89%&#xff09;。結合本源量子云、百度量子等國內平臺免費配額政策&#xff0c;系統性闡述量子神經網絡開發的技術路線與資源獲…

ESP32之本地HTTP服務器OTA固件升級流程,基于VSCode環境下的ESP-IDF開發(附源碼)

背景知識&#xff1a; 本實驗利用編譯鏈內Python內置的 HTTP 服務器&#xff0c;將升級包通過http發送給設備&#xff0c;實現OTA固件升級。 目錄 背景知識&#xff1a; 1.創建工程 1.1 創建OTA基礎工程 3.編寫、修改代碼 3.1 修改menuconfig配置文件 3.1.1 配置WiFi賬…

BootStrap:進階使用(其一)

今天我要講述的是在BootStrap中進一步使用的方法與代碼舉例; 導航條 作為在應用或網站中作為導航頁頭的響應式基礎組件。導航條在移動設備上可以折疊&#xff08;且可開可關&#xff09;&#xff0c;在視口&#xff08;viewport&#xff09;寬度增加時逐漸變為水平展開模式 …

ffmpeg無損轉格式的命令行

將ffmpeg.exe拖入命令行窗口 c:\users\zhangsan>D:\ffmpeg-2025-03-11\bin\ffmpeg.exe -i happy.mp4 -c:v copy -c:a copy 格式轉換后.mkv -c:v copy 僅做拷貝視頻,不重新編碼 -c:a copy 僅做拷貝音頻 ,不重新編碼

【Linux】深入理解Linux文件系統:從C接口到內核設計哲學

文章目錄 前言一、C語言中的文件接口1. 文件指針&#xff08;句柄&#xff09;FILE*以寫方式打開文件&#xff0c;若文件不存在會新建一個文件W寫入方式&#xff0c;在打開文件之前都會將文件內容全部清空追加寫方式&#xff0c;其用法與寫方法一致&#xff0c;不同在于a方法可…

國產品牌芯洲科技100V降壓芯片系列

SCT2A25采用帶集成環路補償的恒導通時間(COT)模式控制&#xff0c;大大簡化了轉換器的片外配置。SCT2A25具有典型的140uA低靜態電流&#xff0c;采用脈沖頻率調制(PFM)模式&#xff0c;它使轉換器在輕載或空載條件下實現高轉換效率。 芯洲科技100V降壓芯片系列提供豐富的48V系…

ctfshow-大賽原題-web702

因為該題沒有理解到位&#xff0c;導致看wp也一直出錯&#xff0c;特此反思一下。 參考yu22x師傅的文章 &#xff1a;CTFSHOW大賽原題篇(web696-web710)_ctfshow 大賽原題-CSDN博客 首先拿到題目&#xff1a; // www.zip 下載源碼 我們的思路就是包含一個css文件&#xff0c;…

LabVIEW技巧——獲取文件版本信息

獲取可執行文件&#xff08;exe&#xff09;版本信息的幾種方法 方法1. LabVIEW自帶函數 labview自帶了獲取文件版本號的VI&#xff0c;但是沒有開放到程序框圖的函數選板中&#xff0c;在該目錄下可以找到&#xff1a;...\LabVIEW 20xx\vi.lib\Platform\fileVersionInfo.llb…

三格電子——CAN 轉光纖(點對點)布線常見問題

1、CAN 布線 &#xff08;1&#xff09;H 接 H ,L 接 L &#xff08;2&#xff09;兩端設備掛 120 歐姆電阻 2、假如用點對點的 CAN 轉光纖現實遠程傳輸 &#xff08;1&#xff09;H 接 H ,L 接 L &#xff08;2&#xff09;光端機都掛 120 歐姆電阻 每個光端機掛的設備有一個加…

python進階: 深入了解調試利器 Pdb

Python是一種廣泛使用的編程語言&#xff0c;以其簡潔和可讀性著稱。在開發和調試過程中&#xff0c;遇到錯誤和問題是不可避免的。Python為此提供了一個強大的調試工具——Pdb&#xff08;Python Debugger&#xff09;。 Pdb是Python標準庫中自帶的調試器&#xff0c;可以幫助…