策略模式詳解

策略模式

1 概述

先看下面的圖片,我們去旅游選擇出行模式有很多種,可以騎自行車、可以坐汽車、可以坐火車、可以坐飛機。

請添加圖片描述

作為一個程序猿,開發需要選擇一款開發工具,當然可以進行代碼開發的工具有很多,可以選擇Idea進行開發,也可以使用eclipse進行開發,也可以使用其他的一些開發工具。

請添加圖片描述

定義:

? 該模式定義了一系列算法,并將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬于對象行為模式,它通過對算法進行封裝,把使用算法的責任和算法的實現分割開來,并委派給不同的對象對這些算法進行管理。

2 結構

策略模式的主要角色如下:

  • 抽象策略(Strategy)類:這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。
  • 具體策略(Concrete Strategy)類:實現了抽象策略定義的接口,提供具體的算法實現或行為。
  • 環境(Context)類:持有一個策略類的引用,最終給客戶端調用。

3 案例實現

【例】促銷活動

一家百貨公司在定年度的促銷活動。針對不同的節日(春節、中秋節、圣誕節)推出不同的促銷活動,由促銷員將促銷活動展示給客戶。類圖如下:

請添加圖片描述

代碼如下:

定義百貨公司所有促銷活動的共同接口

public interface Strategy {void show();
}

定義具體策略角色(Concrete Strategy):每個節日具體的促銷活動

//為春節準備的促銷活動A
public class StrategyA implements Strategy {public void show() {System.out.println("買一送一");}
}//為中秋準備的促銷活動B
public class StrategyB implements Strategy {public void show() {System.out.println("滿200元減50元");}
}//為圣誕準備的促銷活動C
public class StrategyC implements Strategy {public void show() {System.out.println("滿1000元加一元換購任意200元以下商品");}
}

定義環境角色(Context):用于連接上下文,即把促銷活動推銷給客戶,這里可以理解為銷售員

public class SalesMan {                        //持有抽象策略角色的引用                              private Strategy strategy;                 public SalesMan(Strategy strategy) {       this.strategy = strategy;              }                                          //向客戶展示促銷活動                                public void salesManShow(){                strategy.show();                       }                                          
}                                              

4 優缺點

1、優點:

  • 策略類之間可以自由切換

    由于策略類都實現同一個接口,所以使它們之間可以自由切換。

  • 易于擴展

    增加一個新的策略只需要添加一個具體的策略類即可,基本不需要改變原有的代碼,符合“開閉原則“

  • 避免使用多重條件選擇語句(if else),充分體現面向對象設計思想。

2、缺點:

  • 客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。
  • 策略模式將造成產生很多策略類,可以通過使用享元模式在一定程度上減少對象的數量。

5 使用場景

  • 一個系統需要動態地在幾種算法中選擇一種時,可將每個算法封裝到策略類中。
  • 一個類定義了多種行為,并且這些行為在這個類的操作中以多個條件語句的形式出現,可將每個條件分支移入它們各自的策略類中以代替這些條件語句。
  • 系統中各算法彼此完全獨立,且要求對客戶隱藏具體算法的實現細節時。
  • 系統要求使用算法的客戶不應該知道其操作的數據時,可使用策略模式來隱藏與算法相關的數據結構。
  • 多個類只區別在表現行為不同,可以使用策略模式,在運行時動態選擇具體要執行的行為。

6 JDK源碼解析

Comparator 中的策略模式。在Arrays類中有一個 sort() 方法,如下:

public class Arrays{public static <T> void sort(T[] a, Comparator<? super T> c) {if (c == null) {sort(a);} else {if (LegacyMergeSort.userRequested)legacyMergeSort(a, c);elseTimSort.sort(a, 0, a.length, c, null, 0, 0);}}
}

Arrays就是一個環境角色類,這個sort方法可以傳一個新策略讓Arrays根據這個策略來進行排序。就比如下面的測試類。

public class demo {public static void main(String[] args) {Integer[] data = {12, 2, 3, 2, 4, 5, 1};// 實現降序排序Arrays.sort(data, new Comparator<Integer>() {public int compare(Integer o1, Integer o2) {return o2 - o1;}});System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]}
}

這里我們在調用Arrays的sort方法時,第二個參數傳遞的是Comparator接口的子實現類對象。所以Comparator充當的是抽象策略角色,而具體的子實現類充當的是具體策略角色。環境角色類(Arrays)應該持有抽象策略的引用來調用。那么,Arrays類的sort方法到底有沒有使用Comparator子實現類中的 compare() 方法嗎?讓我們繼續查看TimSort類的 sort() 方法,代碼如下:

class TimSort<T> {static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,T[] work, int workBase, int workLen) {assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;int nRemaining  = hi - lo;if (nRemaining < 2)return;  // Arrays of size 0 and 1 are always sorted// If array is small, do a "mini-TimSort" with no mergesif (nRemaining < MIN_MERGE) {int initRunLen = countRunAndMakeAscending(a, lo, hi, c);binarySort(a, lo, hi, lo + initRunLen, c);return;}...}   private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) {assert lo < hi;int runHi = lo + 1;if (runHi == hi)return 1;// Find end of run, and reverse range if descendingif (c.compare(a[runHi++], a[lo]) < 0) { // Descendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)runHi++;reverseRange(a, lo, runHi);} else {                              // Ascendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)runHi++;}return runHi - lo;}
}

上面的代碼中最終會跑到 countRunAndMakeAscending() 這個方法中。我們可以看見,只用了compare方法,所以在調用Arrays.sort方法只傳具體compare重寫方法的類對象就行,這也是Comparator接口中必須要子類實現的一個方法。

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

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

相關文章

JavaScript的跳轉傳參方式

在JavaScript中&#xff0c;頁面跳轉并傳遞參數通常可以通過幾種不同的方式來實現。下面是一些常見的方法&#xff1a; 1.URL參數&#xff08;Query String&#xff09; 這是最常見的方式&#xff0c;通過在URL的末尾添加參數來實現。例如&#xff1a; javascriptwindow.loc…

gitlab webhook觸發jenkins任務

配置jenkins 安裝gitlab插件 配置jenkins job 選擇gitlab webhook觸發 在高級中生成token 代碼倉設置 新增webhook 配置webhook 測試連接 缺點&#xff0c;不能帶gitLab事件的參數&#xff01;&#xff01;&#xff01;

Spark RDD案例:統計網站每月訪問量

這個項目利用Spark技術&#xff0c;通過統計網站訪問記錄中的日期信息&#xff0c;實現了對每月訪問量的統計和排序。通過分析數據&#xff0c;我們可以了解到不同月份的網站訪問情況&#xff0c;為進一步優化網站內容和推廣策略提供數據支持。 使用Spark統計網站每月訪問量 …

Apache2.4和PHP8的量子糾纏

Apache不建議你用&#xff0c;PHP建議使用

一種基于電場連續性的高壓MOSFET緊湊模型,用于精確表征電容特性

來源&#xff1a;A Compact Model of High-Voltage MOSFET Based on Electric Field Continuity for Accurate Characterization of Capacitance&#xff08;TED 24年&#xff09; 摘要 本文提出了一種新的高壓MOSFET&#xff08;HV MOS&#xff09;緊湊模型&#xff0c;以消…

P5732 楊輝三角

題目描述 給出 &#x1d45b;(&#x1d45b;≤20)n(n≤20)&#xff0c;輸出楊輝三角的前 &#x1d45b;n 行。 如果你不知道什么是楊輝三角&#xff0c;可以觀察樣例找找規律。 輸入格式 無 輸出格式 無 輸入輸出樣例 輸入 #1復制 6 輸出 #1復制 1 1 1 1 2 1 1 3 3 …

408學習筆記-數據結構-2-線性表

線性表 1、邏輯結構 1、數據結構只有一種邏輯結構&#xff0c;而可以有兩種存儲結構&#xff0c;有多種抽象運算。 2、線性表是一種邏輯結構&#xff0c;屬于總線性結構——線性結構的一種&#xff0c;同屬于線性結構的邏輯結構還有&#xff1a;棧、隊列和數組。 3、線性表定…

【經典文獻】水下光學和聲學成像:融合的時代?最新技術概述

文獻名稱&#xff1a;《Underwater Optical and Acoustic Imaging: A Time for Fusion? A Brief Overview of the State-of-the-Art》作者列表&#xff1a;Fausto Ferreira, Diogo Machado, Gabriele Ferri, Samantha Dugelay and John Potter作者單位&#xff1a;北約科學技術…

【hana】hana1.0多容器常用命令

基礎命令 數據庫 連接數據庫 hdbsql -u system -p {passwd} -i 02 -d {dbname}查詢所有數據庫 SELECT DATABASE_NAME, ACTIVE_STATUS FROM M_DATABASES;停止數據庫&#xff0c;會修改數據庫狀態為No ALTER SYSTEM STOP DATABASE testdb; 啟動數據庫&#xff0c;會修改數據…

多線程的代碼案例

目錄 單例模式 餓漢模式 懶漢模式 阻塞隊列 生產者消費者模型意義: 阻塞隊列使用方法 實現阻塞隊列 阻塞隊列實現生產者消費者模型 定時器 實現簡單的定時器 工廠模式 線程池 為啥呢? 從池子里面取 比 創建線程 效率更高 線程池的創建 怎么填坑 ThreadPoolExec…

多年后,再探算法和數據結構

多年來&#xff0c;通過深入學習和實踐各種編程語言&#xff0c;我對數據結構和算法在程序設計中的中心地位有了新的認識。本次從匯編語言到高級編程語言的探討&#xff0c;展示了無論技術如何進步&#xff0c;構成程序的核心—算法和數據結構—始終保持其基礎和不變的角色。 …

圖解堆排序【一眼看穿邏輯思路】

P. S.&#xff1a;以下代碼均在VS2019環境下測試&#xff0c;不代表所有編譯器均可通過。 P. S.&#xff1a;測試代碼均未展示頭文件stdio.h的聲明&#xff0c;使用時請自行添加。 目錄 1、堆的概念2、實現堆排序前的準備工作3、堆排序的思路3.1 第一步3.2 第二步 4、結語 1、…

音視頻捕捉技術:LCC382 SDI采集卡深度解析

在日新月異的多媒體時代&#xff0c;高質量的音視頻采集已成為眾多領域不可或缺的一環。為此&#xff0c;靈卡科技精心打造了LCC382 —— 一款集高效性、靈活性與前沿技術于一身的SDI輸入與環出、HDMI輸出音視頻采集卡&#xff0c;旨在滿足從專業直播、視頻會議到醫療影像、安防…

網頁版Figma漢化

最近學習Figma&#xff0c;簡單介紹一下網頁版Figma的漢化方法 1.打開網址&#xff1a;Figma軟件漢化-Figma中文版下載-Figma中文社區 2.下載漢化插件離線包 解壓漢化包 3.點開谷歌的管理擴展程序 4.點擊加載已解壓的擴展程序&#xff0c;選擇剛剛解壓的包 這樣就安裝好了漢化…

QT狀態機2-含終止狀態的嵌套狀態機

#include "MainWindow.h" #include "ui_MainWindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)

前饋神經網絡FNN、多層感知機MLP和反向傳播推導

目錄 一、前饋神經網絡FNN 激活函數的使用 二、多層感知機MLP MLP的典型結構 多層感知機MLP的特點 和前饋神經網絡FNN的區別 三、傳播推導 1、前向傳播(Forward propagation) &#xff08;1&#xff09;輸入層到隱藏層 &#xff08;2&#xff09;隱藏層到輸出層 2、…

Java面試八股之WeakHashMap的工作原理

簡述WeakHashMap的工作原理 弱鍵&#xff08;Weak Keys&#xff09;&#xff1a; WeakHashMap 的鍵&#xff08;keys&#xff09;是通過 WeakReference 弱引用進行封裝的。弱引用是一種特殊的引用類型&#xff0c;它不會阻止所引用的對象被垃圾收集器回收。這意味著&#xff…

冥想訓練具體方法有哪些|流靜冥想

冥想是一種身體的放松和敏銳的警覺性相結合的狀態。 每日練習的好處遠不止你花在集中注意力的那幾分鐘。桑托雷利是建在烏斯特的馬薩諸塞大學醫學院的減壓診所的所長&#xff0c;她也是《自愈》的作者&#xff0c;她說&#xff1a;"冥想是一種工具&#xff0c;通過練習&a…

ubuntu無法遠程連接,ssh不可用,ssh遠程連接被拒絕的解決方法。啟動sshd遠程連接

1、用以下命令檢查ssh狀態 systemctl status sshd2、如果查不到sshd狀態&#xff0c;或提示沒有ssh&#xff0c;就安裝ssh服務器和客戶機 $ sudo apt install openssh-server # 安裝ssh服務器 $ sudo apt install openssh-client # 安裝ssh客戶機3、如果不能安裝openssh-…