Strategy 策略模式

意圖

定義一系列的算法,把它們一個個封裝起來, 并且使它們可相互替換。本模式使得算法可獨立于使用它的客戶而變化。

動機

策略模式為了適應不同的需求,只把變化點封裝了,這個變化點就是實現不同需求的算法,但是,用戶需要知道各種算法的具體情況。就像上面的加班工資,不同的加班情況,有不同的算法。我們不能在程序中將計算工資的算法進行硬編碼,而是能自由的變化的。這就是策略模式。

剛剛加班回來;哎,公司規定平時加班只有10塊錢的餐補;星期六和星期天加班,只給串休假;在國家規定的節假日按照3倍工資發放。那么對于這么多的計算加班費的方法,公司的OA系統是如何進行做的呢?各種計算加班費的情況就可以認為是策略模式

適用性

  • 許多相關的類僅僅是行為有異。 “策略”提供了一種用多個行為中的一個行為來配置一個類的方法。
  • 需要使用一個算法的不同變體。例如,你可能會定義一些反映不同的空間 /時間權衡的算法。當這些變體實現為一個算法的類層次時,可以使用策略模式
  • 算法使用客戶不應該知道的數據。可使用策略模式以避免暴露復雜的、與算法相關的數據結構。
  • 一個類定義了多種行為 , 并且這些行為在這個類的操作中以多個條件語句的形式出現。將相關的條件分支移入它們各自的Strategy類中以代替這些條件語句。

結構

?

參與者

Strategy:定義所有支持的算法的公共接口。Context使用這個接口來調用某ConcreteStrategy定義的算法;
ConcreteStrategy:實現Strategy接口的具體算法;
Context:使用一個ConcreteStrategy對象來配置;維護一個對Stategy對象的引用,同時,可以定義一個接口來讓Stategy訪問它的數據。

效果

相關算法系列Strategy類層次為Context定義了一系列的可供重用的算法或行為。繼承有助于析取出這些算法中的公共功能。

實現

純策略模式,實際上就是父類為純虛函數,子類根據需求實現各種方法

 1 #include <iostream>
 2 using namespace std;
 3 
 4 // The abstract strategy
 5 class Strategy
 6 {
 7 public:
 8      virtual void AlgorithmInterface() = 0;
 9 };
10 
11 class ConcreteStrategyA : public Strategy
12 {
13 public:
14      void AlgorithmInterface()
15      {
16           cout<<"I am from ConcreteStrategyA."<<endl;
17      }
18 };
19 
20 class ConcreteStrategyB : public Strategy
21 {
22 public:
23      void AlgorithmInterface()
24      {
25           cout<<"I am from ConcreteStrategyB."<<endl;
26      }
27 };
28 
29 class ConcreteStrategyC : public Strategy
30 {
31 public:
32      void AlgorithmInterface()
33      {
34           cout<<"I am from ConcreteStrategyC."<<endl;
35      }
36 };
37 
38 class Context
39 {
40 public:
41      Context(Strategy *pStrategyArg) : pStrategy(pStrategyArg)
42      {
43      }
44      void ContextInterface()
45      {
46           pStrategy->AlgorithmInterface();
47      }
48 private:
49      Strategy *pStrategy;
50 };
51 
52 int main()
53 {
54      // Create the Strategy
55      Strategy *pStrategyA = new ConcreteStrategyA;
56      Strategy *pStrategyB = new ConcreteStrategyB;
57      Strategy *pStrategyC = new ConcreteStrategyC;
58      Context *pContextA = new Context(pStrategyA);
59      Context *pContextB = new Context(pStrategyB);
60      Context *pContextC = new Context(pStrategyC);
61      pContextA->ContextInterface();
62      pContextB->ContextInterface();
63      pContextC->ContextInterface();
64 
65      if (pStrategyA) delete pStrategyA;
66      if (pStrategyB) delete pStrategyB;
67      if (pStrategyC) delete pStrategyC;
68 
69      if (pContextA) delete pContextA;
70      if (pContextB) delete pContextB;
71      if (pContextC) delete pContextC;
72 }

在實際操作的過程中,我們會發現,在main函數中,也就是在客戶端使用策略模式時,會創建非常多的Strategy,而這樣就莫名的增加了客戶端的壓力,讓客戶端的復雜度陡然增加了。那么,我們就可以借鑒簡單工廠模式,使策略模式和簡單工廠模式相結合,從而減輕客戶端的壓力,代碼實現如下:

  1 #include <iostream>
  2 using namespace std;
  3 
  4 // Define the strategy type
  5 typedef enum StrategyType
  6 {
  7     StrategyA,
  8     StrategyB,
  9     StrategyC
 10 }STRATEGYTYPE;
 11 
 12 // The abstract strategy
 13 class Strategy
 14 {
 15 public:
 16     virtual void AlgorithmInterface() = 0;
 17     virtual ~Strategy() = 0; // 謝謝hellowei提出的bug,具體可以參見評論
 18 };
 19 
 20 Strategy::~Strategy()
 21 {}
 22 
 23 class ConcreteStrategyA : public Strategy
 24 {
 25 public:
 26     void AlgorithmInterface()
 27     {
 28         cout << "I am from ConcreteStrategyA." << endl;
 29     }
 30 
 31     ~ConcreteStrategyA(){}
 32 };
 33 
 34 class ConcreteStrategyB : public Strategy
 35 {
 36 public:
 37     void AlgorithmInterface()
 38     {
 39         cout << "I am from ConcreteStrategyB." << endl;
 40     }
 41 
 42     ~ConcreteStrategyB(){}
 43 };
 44 
 45 class ConcreteStrategyC : public Strategy
 46 {
 47 public:
 48     void AlgorithmInterface()
 49     {
 50         cout << "I am from ConcreteStrategyC." << endl;
 51     }
 52 
 53     ~ConcreteStrategyC(){}
 54 };
 55 
 56 class Context
 57 {
 58 public:
 59     Context(STRATEGYTYPE strategyType)
 60     {
 61         switch (strategyType)
 62         {
 63         case StrategyA:
 64             pStrategy = new ConcreteStrategyA;
 65             break;
 66 
 67         case StrategyB:
 68             pStrategy = new ConcreteStrategyB;
 69             break;
 70 
 71         case StrategyC:
 72             pStrategy = new ConcreteStrategyC;
 73             break;
 74 
 75         default:
 76             break;
 77         }
 78     }
 79 
 80     ~Context()
 81     {
 82         if (pStrategy) delete pStrategy;
 83     }
 84 
 85     void ContextInterface()
 86     {
 87         if (pStrategy)
 88             pStrategy->AlgorithmInterface();
 89     }
 90 
 91 private:
 92     Strategy *pStrategy;
 93 };
 94 
 95 int main()
 96 {
 97     Context *pContext = new Context(StrategyA);
 98     pContext->ContextInterface();
 99 
100     if (pContext) delete pContext;
101 }

?

轉載于:https://www.cnblogs.com/raichen/p/5673575.html

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

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

相關文章

python 消息中間件_消息隊列中間件 RabbitMQ 詳細介紹——安裝與基本應用(Python)...

RabbitMQ 是當前最流行的消息中間件(Message Broker)之一&#xff0c;支持多種消息協議(如 AMQP、MQTT)。同時它也是一個輕量級的非常易于部署的開源軟件&#xff0c;可以運行在當前大多數操作系統及云端環境中&#xff0c;也能夠部署在分布式的集群環境里以達到高可用、可伸縮…

用 Flask 來寫個輕博客 (1) — 創建項目

目錄 目錄前言擴展閱讀部署開發環境創建 Github 項目前言 一步一步的實現一個 Flask 輕博客項目啟動&#xff0c;最新的代碼會上傳到 Github。 擴展閱讀 歡迎使用 Flask — virtualenv 部署開發環境 連接 GitHubhostnamectl set-hostname flask-dev # 設置 hostname ssh-keyg…

python靜態方法,類方法,屬性方法,實例方法

DAY 3. 靜態方法&#xff0c;類方法&#xff0c;屬性方法&#xff0c;實例方法 有四種方法&#xff0c;實例方法&#xff0c;類方法&#xff0c;靜態方法&#xff0c;屬性方法 實例方法 實例方法的第一個參數是self&#xff0c;他會指向類的實例化對象&#xff0c;只能被對象…

ubuntu 軟件包降級

ubuntu 軟件包降級 sudo aptitude install libssl-dev 1. 是否接受該解決方案&#xff1f; [Y/n/?] n 2. 是否接受該解決方案&#xff1f; [Y/n/?] y 3. 您要繼續嗎&#xff1f; [Y/n/?] ysudo aptitude install libcairo21.4.10-1ubuntu4 # 強制降級 sudo aptitude forbid…

java后期發展方向_Java程序員的4個職業發展方向,該如何把握黃金5年?

在Java程序界流行著一種默認的說法叫“黃金5年”&#xff0c;意思是說&#xff0c;一個Java程序員從入職的時候算起&#xff0c;前五年我選擇直接影響著整個職業生涯的發展方向和薪資走向。而這5年&#xff0c;也決定了一個程序員能否成為職業大牛的可能。那么&#xff0c;在這…

python 類變量(屬性)和實例變量(屬性

DAY 4. 類變量&#xff08;屬性&#xff09;和實例變量&#xff08;屬性&#xff09; 類變量&#xff1a;在所有類的實例之間都可以共享的變量&#xff0c;類變量在所有對象間只保留一份 在類體中定義類的所有實例對象都可以訪問類變量類變量只能由類修改&#xff0c;實例對象…

MySQL 關聯表批量修改(數據同步)

update table1 t1 ,table2 t2 set t1.field1 t2.field2 where t1.id t2.id 轉載于:https://www.cnblogs.com/52php/p/5677908.html

sourcetree不好做到的一些git操作

2019獨角獸企業重金招聘Python工程師標準>>> 日常中我們有很多操作通過sourcetree就可以實現界面化操作&#xff0c;但是有一些場景不好去實現&#xff0c;這里總結下&#xff1a; 場景1&#xff1a;我們有個A分支&#xff0c;需要跟master分支合并等待上線&#xf…

vue大括號里接受一個函數_vue源碼探究(第四彈)

vue源碼探究&#xff08;第四彈&#xff09;結束了上一part的數據代理&#xff0c;這一部分主要講講vue的模板解析&#xff0c;感覺這個有點難理解&#xff0c;而且內容有點多&#xff0c;hhh。模板解析廢話不多說&#xff0c;先從簡單的入手。按照之前的套路&#xff0c;先舉一…

類級別的分裝 ---四種訪問級別

privateprivate成員為類的私有性質&#xff0c;僅有類本身和友元可以訪問&#xff1b;protected和private類似&#xff0c;區別于protected可以被該類所有派生類訪問&#xff1b;publicpublic的成員可以被外界的所有客戶代碼直接訪問published和public的區別僅在于published的成…

python自省與反射

DAY 5. python自省 這是很久之前寫的&#xff0c;當時對自省和反射的概念沒理解&#xff0c;學習Java以后多了一點理解&#xff0c;自省是獲取對象的能力&#xff0c;反射是操縱對象的能力&#xff0c;python中使用getattr()和setattr()實現反射&#xff0c;而其他的則是自省&…

vb.net 窗體接收鍵盤事件_(十五)C#WinFrom自定義控件系列-鍵盤(二)

前提入行已經7,8年了&#xff0c;一直想做一套漂亮點的自定義控件&#xff0c;于是就有了本系列文章。本系列文章將講解各種控件的開發及思路&#xff0c;歡迎各位批評指正。此系列控件開發教程將全部在原生控件基礎上進行重繪開發&#xff0c;目標的扁平化、漂亮、支持觸屏。如…

centos下cmake安裝

步驟一、安裝gcc等必備程序包&#xff08;已安裝則略過此步&#xff0c;用gcc -v檢測&#xff09; yum install -y gcc gcc-c make automake 步驟二、安裝wget &#xff08;已安裝則略過此步&#xff09; yum install -y wget 步驟三、獲取CMake源碼包 wget http://www.cmake.…

python 生成式,迭代器,生成器

DAY 6. 生成式,迭代器&#xff0c;生成器 6.1 生成式 6.1.1 列表生成式 list [index for index in range(10)]6.1.2 字典生成式 dict {zhangsan: 10,lisi: 12,wangwu: 18 } # 實現鍵值互換 dict {k:v for v,k in dict.items() if k > 12}6.1.3 集合生成式 # 100以內…

shell MAC 地址 校驗

/**************************************************************************************** shell MAC 地址 校驗* 說明&#xff1a;* 要對MAC地址進行校驗&#xff0c;記錄一下正則表達式寫法&#xff0c;有些方法在PC上驗證是可行的&…

移動端Web開發如何處理橫豎屏

<!Doctype html> <html> <head> <meta charset"utf-8"> <meta id"viewport" name"viewport" content"widthdevice-width,initial-scale1.0;"> <title>橫豎屏切換檢測</title> <style ty…

恩智浦智能車大賽2020_內蒙古科技大學第九屆智能車大賽校內公開賽總決賽

為了激發學生的創新意識&#xff0c;提高學生的動手能力&#xff0c;培養團隊合作意識&#xff0c;秉承“實踐源于真知&#xff0c;創新放飛夢想”的思想。2020年12月6日&#xff0c;內蒙古科技大學第九屆智能車大賽總決賽如約而至。本次大賽有來自各院系的223支隊伍報名參加了…

python格式化字符串的三種方法(%,format,f-string)

DAY 7. 格式化字符串 到目前為止&#xff0c;我所知道的&#xff0c;python格式化字符串有三種方法&#xff0c;第一是早期就有的%&#xff0c;其次是2.5之后的format(),還有就是3.6添加的f字符串調試 7.1 %格式化字符串 %格式化字符串是python最早的&#xff0c;也是能兼容…

Android App 優化之 ANR 詳解

為了便于閱讀, 應邀將Android App性能優化系列, 轉移到掘金原創上來.掘金的新出的"收藏集"功能可以用來做系列文集了. 今天先來聊聊ANR. 1, 你碰到ANR了嗎 在App使用過程中, 你可能遇到過這樣的情況: 恭喜你, 這就是傳說中的ANR. 1.1 何為ANR ANR全名Application Not…

微信高級群發接口正文亂碼解決方案

content里面的內空如果含有html標簽的話&#xff0c;需要對內容進行一下轉義。如果里面含有style".."類似于這樣的帶""號的內容的話&#xff0c;就更需要注意了。 foreach ($news as &$item) {foreach ($item as $key > $val){if ($key content){$…