設計模式--Strategy 策略模式

? 所謂策略模式(Strategy Pattern),就是將策略 (算法) 封裝為一個對象,易于相互替換,如同 USB 設備一樣可即插即用;如果將策略、具體的算法和行為,編碼在某個類或客戶程序內部,將導至事后的修改和擴展不易。
? 當有多種「策略」時,通常的作法就是將這些個策略,和這些策略的算法、行為,分別封裝在各個類中,并讓這些類,去繼承某個公用的抽象類或接口。接著在客戶 程序中,就可動態引用,且易于更換這些不同的「策略」,不會因為日后添加、修改了某一個「策略」,就得重新修改、編譯多處的源代碼。此即為一種「封裝變化 點」的做法,將常會變化的部分進行抽象、定義為接口,亦即實現「面向接口編程」的概念。且客戶程序 (調用者) 只須知道接口的外部定義即可,具體的實現則無須理會。
?? 策略模式(Strategy Pattern)在外形上與狀態模式很相似,但在意圖上有些不同。其意圖是使這些算法可以相互替換,并提供一種方法來選擇最合適的算法。
?? 策略模式(Strategy Pattern)的UML圖如下:

????????????????????????
在策略模式里主要有三種角色:環境角色、抽象策略角色和具體策略角色
1、環境(Context)角色:持有一個抽象策略(Strategy)角色的引用。也叫上下文。
2、抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或一個抽象類來實現。
3、具體策略(ConcreteStrategy)角色:包裝了相應的算法和行為。
下面我們用代碼來示例策略模式,程序如下圖:

????????????????????????
一、策略模式基本思路示例

1、環境(Context)角色:

ContractedBlock.gifExpandedBlockStart.gif
using?System;
using
?System.Collections.Generic;
using
?System.Linq;
using
?System.Text;

namespace
?MyStrategyPattern
{
????
#region?定義Context類

????
class?Context
????{
????????
private
?Strategy?_strategy;

????????
#region?構造函數

????????
public?Context(Strategy?strategy)
????????{
????????????
this._strategy?=
?strategy;
????????}
????????
#endregion


????????
#region?定義算法接口
????????
//具體的算法由傳入的strategy對象的AlgorithmInterface方法來實現
????????public?void?ContextInterface()
????????{
????????????_strategy.AlgorithmInterface();
???????
?}
????????#endregion

????}
????
#endregion
}
2、抽象策略(Strategy)角色:
ContractedBlock.gifExpandedBlockStart.gif
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;

namespace?MyStrategyPattern
{
????
#region?抽象策略類Strategy,定義了具體策略類的共有算法接口
????
abstract??class?Strategy
????{
????????
public?abstract?void?AlgorithmInterface();
????}
????
#endregion
}
3、具體策略(ConcreteStrategy)角色:
ContractedBlock.gifExpandedBlockStart.gif
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;

namespace?MyStrategyPattern
{?
????
//定義了一系列的具體策略類,它們繼承自抽象策略類

????
class?ConcreteStrategyA?:?Strategy
????{
????????
public?override?void?AlgorithmInterface()
????????{
????????????Console.WriteLine(
"使用了算法A來處理Context對象");
????????}
????}

????
class?ConcreteStrategyB?:?Strategy
????{
????????
public?override?void?AlgorithmInterface()
????????{
????????????Console.WriteLine(
"使用了算法B來處理Context對象");
????????}
????}

????
class?ConcreteStrategyC?:?Strategy
????{
????????
public?override?void?AlgorithmInterface()
????????{
????????????Console.WriteLine(
"使用了算法C來處理Context對象");
????????}
????}
}
4、客戶應用代碼
ContractedBlock.gifExpandedBlockStart.gif
????????????#region?基本思路示例
????????????Console.WriteLine(
"----策略模式基本思路示例----");
????????????Context?context;
????????????
//調用不同的算法來處理對象,算法的差異在Context傳參時(new?ConcreteStrategyA())決定
????????????context?=?new?Context(new?ConcreteStrategyA());
????????????context.ContextInterface();

????????????context?
=?new?Context(new?ConcreteStrategyB());
????????????context.ContextInterface();

????????????context?
=?new?Context(new?ConcreteStrategyC());
????????????context.ContextInterface();


????????????
#endregion

二、求和計算的策略模式示例
1、環境(Context)角色:CalculateContext.

ContractedBlock.gifExpandedBlockStart.gif
using?System;
using
?System.Collections.Generic;
using
?System.Linq;
using
?System.Text;

namespace
?MyStrategyPattern
{
????
class
?CalculateContext
????{
????????ICalculateStrategy?_strategy;
????????
public
?CalculateContext(ICalculateStrategy?strategy)
????????{
????????????_strategy?
=
?strategy;
????????}

????????
public?void?PerformCalculation(List<int>
?list)
????????{
????????????Console.WriteLine(
string.Format("對列表中所有整數求和,結果為:{0}"
,?_strategy.Sum(list)));
????????}
????}
}

2、抽象策略(Strategy)角色:ICalculateStrategy

ContractedBlock.gifExpandedBlockStart.gif
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;

namespace?MyStrategyPattern
{
????
interface??ICalculateStrategy
????{
????????
int?Sum(List<int>?list);
????}
}

3、具體策略(ConcreteStrategy)角色:CalculateStrategies


ContractedBlock.gifExpandedBlockStart.gif
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;

namespace?MyStrategyPattern
{
????
#region?方法A
????
class?ConcreteCalculateStrategyA?:?ICalculateStrategy
????{
????????
//利用List的Sum功能對List中整數求和
????????public?int?Sum(List<int>?list)
????????{
????????????Console.WriteLine(
"----。使用方法A進行求和----");
????????????
return?list.Sum();
????????}
????}
????
#endregion

????
#region?方法B
????
class?ConcreteCalculateStrategyB?:?ICalculateStrategy
????{
????????
//使用傳統的遍歷方法,對List中整數求和
????????public?int?Sum(List<int>?list)
????????{
????????????Console.WriteLine(
"----。使用方法B進行求和----");
????????????
int?result?=?0;
????????????
foreach(int?value?in?list)
????????????{
????????????????result?
+=?value;
????????????}
????????????
return?result;
????????}
????}
????
#endregion


}

4、客戶應用代碼

ContractedBlock.gifExpandedBlockStart.gif
???????????#region?求和計算的策略模式示例
????????????Console.WriteLine(
"\n\n----求和計算的策略模式示例----");
????????????List
<int>?lst?=?new?List<int>
();
????????????lst.Add(
3
);
????????????lst.Add(
6
);
????????????lst.Add(
8
);
????????????lst.Add(
9
);

????????????CalculateContext?caltext;
????????????caltext?
=?new?CalculateContext(new
?ConcreteCalculateStrategyA());
????????????caltext.PerformCalculation(lst);

????????????caltext?
=?new?CalculateContext(new
?ConcreteCalculateStrategyB());
????????????caltext.PerformCalculation(lst);

????????????Console.ReadKey();

????????????
#endregion

效果如下圖:
????????????????????????

總結:

Strategy Pattern 適用的情景:
1、應用中的許多類,在解決某些問題時很相似,但實現的行為有所差異。比如:不同功能的程序,都可能要用到「排序」算法。
2、根據運行環境的不同,需要采用不同的算法。比如:在手機、PC 計算機上,因硬件等級不同,必須采用不同的排序算法。
3、針對給定的目的,存在多種不同的算法,且我們可用代碼實現算法選擇的標準。
4、需要封裝復雜的數據結構。比如:特殊的加密算法,客戶程序僅需要知道調用的方式即可。
5、同上,算法中的羅輯和使用的數據,應該與客戶程序隔離時。

Strategy Pattern 的優點:
1、簡化了單元測試,因為每個算法都有自己的類,可以通過自己的接口單獨做測試。
2、避免程序中使用多重條件轉移語句,使系統更靈活,并易于擴展。
3、高內聚、低偶合。

Strategy Pattern 的缺點:
1、因為每個具體策略都會產生一個新類,所以會增加需要維護的類的數量。
2、選擇所用具體實現的職責由客戶程序承擔,并轉給 Context 對象,并沒有解除客戶端需要選擇判斷的壓力。
3、若要減輕客戶端壓力,或程序有特殊考量,還可把 Strategy 與 Simple Factory 兩種 Pattern 結合,即可將選擇具體算法的職責改由 Context 來承擔,亦即將具體的算法,和客戶程序做出隔離。

前往:設計模式學習筆記清單
Tag標簽: 設計模式,Strategy策略模式

轉載于:https://www.cnblogs.com/smallfa/archive/2009/11/24/1609456.html

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

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

相關文章

HDU-1518 Square dfs+剪枝

該題問給定的棍子能否組成一個正方形。首先我們要判定是否總長度是4的倍數&#xff0c;然后再決定是否存在某條邊大于組合邊長。 搜索的過程中也是可以進行剪枝了。 首先將邊排序&#xff0c;我們可以假定所有的組合邊由大小遞減的邊組成&#xff0c;那么我們在搜索的時候就不用…

英語思維黃金法則

一、謂語單一原則 英文的句子當中&#xff0c;有且只有一套謂語結構。 要想使用多個謂語&#xff0c;有以下三種方法&#xff1a; 1&#xff0c;利用連詞將不同謂語并列起來 2&#xff0c;把其中的一些動詞給降級&#xff08;v-ing v-ed 非謂語動詞&#xff09; 3&#xff0c;…

java getname_Java文件類字符串getName()方法(帶示例)

java getname文件類字符串getName() (File Class String getName()) This method is available in package java.io.File.getName(). 軟件包java.io.File.getName()中提供了此方法。 This method is used to retrieve or return the filename or directory name and represente…

WF中DependencyObject和DependencyProperty的實現

WF中DependencyObject和DependencyProperty的實現 DependencyProperty的Register和RegisterAttached方法&#xff0c;將DependencyProperty存在IDictionary中完成注冊&#xff0c;確保相同name的DependencyProperty在一個ownerType類型中只能有一個。 DependencyObject的GetVal…

hdu2115: I Love This Game

hdu2115: http://acm.hdu.edu.cn/showproblem.php?pid2115題意&#xff1a;輸入n組名字和對應的時間&#xff08;分&#xff1a;秒&#xff09;&#xff0c;要求按時間長度由短到長排序&#xff0c;并輸出對應排名&#xff0c;若時間一樣&#xff0c;則按名字字典序排序&#…

打開eclipse出現Failed to load the JNI shared library “D:\java\jdk\bin\...\jre\bin\server\jvm.dll”如何解決?

eclipse打開的時候出現Failed to load the JNI shared library “D:\java\jdk\bin…\jre\bin\server\jvm.dll”如何解決&#xff1f;&#xff1f; 如圖所示&#xff1a; 即代表你的jdk與eclipse的位數不一樣&#xff01;&#xff01;&#xff01; 你可以查看一下eclipse和jd…

Java DataOutputStream writeUTF()方法及示例

DataOutputStream類的writeUTF()方法 (DataOutputStream Class writeUTF() method) writeUTF() method is available in java.io package. writeUTF()方法在java.io包中可用。 writeUTF() method is used to write the given string value to the basic data output stream wit…

2010年世界杯分組

A 南非 墨西哥 烏拉圭 法國 B 阿根廷 南非 韓國 希臘 C 英格蘭 美國 阿爾及利亞 斯洛文尼亞 D 德國 澳大利亞 塞爾維亞 加納 E 荷蘭 丹麥 日本 喀麥隆 F 意大利 巴拉圭 新西蘭 斯洛伐克 G 巴西 朝鮮 科特迪瓦 葡萄牙 H 西班牙 瑞士 洪都拉斯 智利 轉載于:https://www.cnblogs.c…

圓形墜落模擬算法設計

目標&#xff1a;實現一個算法&#xff0c;模擬在一個封閉二維區域&#xff0c;圓形小球朝給定方向墜落的過程&#xff0c;實現二維區域的緊密填充。 像下面這樣&#xff1a; 難點&#xff0c;及其簡單解決&#xff1a; 1.如何把粒子移動盡可能遠&#xff1f; 圖中的粒子i&…

Maven詳細教學

一、Maven簡介 maven&#xff1a;是apache下的一個開源項目&#xff0c;是純java開發&#xff0c;并且只是用來管理java項目的 依賴管理&#xff1a;就是對jar包的統一管理 可以節省空間 項目一鍵構建&#xff1a;mvn tomcat:run該代碼可以將一個完整的項目運行起來&#xff0…

Java Character.UnicodeBlock of()方法與示例

Character.UnicodeBlock類的()方法 (Character.UnicodeBlock Class of() method) of() method is available in java.lang package. of()方法在java.lang包中可用。 of() method is used to return the Unicode block containing the given parameter value or it returns null…

simpleDBM的B-link樹實現

參考的是VLDB2005的這篇論文&#xff0c;做個標記把。/Files/YFYkuner/Concurrency_control_and_recovery_for_balanced_B-link_trees.pdf 轉載于:https://www.cnblogs.com/YFYkuner/archive/2009/12/21/1629268.html

網站后臺中對html標簽的處理

最近做一個CMS&#xff0c;后臺中需要使用在線編輯器對新聞進行編輯&#xff0c;然后發表。我用的在線編輯器是CKEditorCKFinder。也許是我為了讓CKEditor更本地化吧&#xff0c;改了很多。后來發現在CKEditor中對文字設置字體、顏色、字號大小時文字的<span>標簽會出現N…

Java Calendar getActualMaximum()方法與示例

日歷類的getActualMaximum()方法 (Calendar Class getActualMaximum() method) getActualMaximum() method is available in java.util package. getActualMaximum()方法在java.util包中可用。 getActualMaximum() method is used to return the maximum value that the given …

軟件研發人員考核的十項基本原則(轉)

軟件研發人員考核的十項基本原則 作者: 任甲林 來源: 萬方數據 軟件研發人員的考核一直是軟件企業管理的難點筆者在長期的研發管理實踐與咨詢實踐中總結了進行軟件研發人員考核的一些基本原則。(1) 要體現公司的價值觀公司的價值觀體現了公司認可什么類型的人員&#xff1f;…

2012.7.24---C#(2)

學習過了C#的基本屬性函數后&#xff0c;接下來的學習我覺得比較重要。C#是一種面向對象的語言&#xff0c;下面復習一下面向對象中的一些名詞。 類&#xff1a;把一些系列東西&#xff0c;把他們的共同的屬性和方法抽象出來&#xff0c;給他起一個名字就是XXX類。類中定義…

匯編語言-001(BYTE、DUP、WORD 、DWORD 、QWORD 、TBYTE 、REAL )

1 : 基礎匯編語言展示 .386 .model flat,stdcall .stack 4096 ExitProcess PROTO,dwExitCode:DWORD.code main PROCmov eax,5add eax,6INVOKE ExitProcess,0 main ENDP END main2:基礎匯編語言展示增加變量的訪問 .386 .model flat,stdcall .stack 4096 ExitProcess PROTO,dw…

<各國地圖輪廓app>技術支持

如在app使用過程中遇到任何問題&#xff0c;請與開發者聯系caohechunhotmail.com

Java BigDecimal longValueExact()方法與示例

BigDecimal類longValueExact()方法 (BigDecimal Class longValueExact() method) longValueExact() method is available in java.math package. longValueExact()方法在java.math包中可用。 longValueExact() method is used to convert this BigDecimal to an exact long val…

c#中的多線程同步

在處理多線程同步問題的時候&#xff0c;我們一般有臨界區&#xff0c;互斥量&#xff0c;信號量和消息機制等幾種解決方案&#xff0c;在c#中可以非常方便的使用它們來實現進程的同步。下面我就常用的lock,Monitor和Mutex幾種來說明如何實現進程的同步。 lock和Monitor依靠一種…