C# 設(shè)計模式系列教程-策略模式
在講策略模式之前,我先給大家舉個日常生活中的例子,從首都國際機場到XXX酒店,怎么過去?1)酒店接機服務(wù),直接開車來接。2)打車過去。3)機場快軌+地鐵 4)機場巴士 5)公交車 6)走路過去(不跑累死的話) 等等。使用方法,我們都可以達到從機場到XXX酒店的目的,對吧。那么我所列出的從機場到XXX酒店的的方法,就是我們可以選擇的策略。
再舉個例子,就是我們使用WCF時,往往避免不了對它進行擴展,例如授權(quán),我們可以通過自定義授權(quán)來擴展WCF。這里我們可以通過自定義AuthorizationPolicy和ServiceAuthorizationManager來實現(xiàn)對它的擴展,這是策略模式的一個真實應(yīng)用。
1. 概述
它定義了算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化不會影響到使用算法的客戶端。
2. 模式中的角色
2.1 策略類(Stratege):定義所有支持的算法的公共接口。
2.2 具體策略類(Concrete Stratege):封裝了具體的算法或行為,繼承于Stratege類。
2.3 上下文類(Context):用一個ConcreteStratege來配置,維護一個對Stratege對象的引用。
對比開篇例子分析一下這個模式中的角色:
在從機場到XXX酒店的這個例子中,策略類中必然要包括GoToHotel這個方法。而具體策略類應(yīng)該實現(xiàn)或繼承策略類,它的實現(xiàn)就不用說了。上下文類,這個類很重要,也很有意思,因為它需要去選擇使用哪個策略,例如這個上下我是我,我要從機場到XXX酒店,1)我根本不差錢,酒店也提供接機服務(wù),那我必然選擇酒店接機呀;2)如果酒店不提供接機我就選擇打的。3)如果我囊中羞澀,就可以選擇公共交通。4)如果我現(xiàn)在錢都花完了,連吃飯的錢都沒有了,那么我只能選擇走路過去了,沒準半道上還得討飯呢!
3. 模式解讀
3.1 策略模式的一般化類圖
3.2 策略模式的代碼實現(xiàn)
/// <summary> /// 策略類,定義了所有支持的算法的公共接口 /// </summary> public abstract class Stratege { /// <summary> /// 策略類中支持的算法,當(dāng)然還可以有更多,這里只定義了一個。 /// </summary> public abstract void Algorithm(); } /// <summary> /// 具體策略 A,實現(xiàn)了一種具體算法 /// </summary> public class ConcreteStrategeA : Stratege { /// <summary> /// 具體算法 /// </summary> public override void Algorithm() { // 策略A中實現(xiàn)的算法 } } /// <summary> /// 具體策略 B,實現(xiàn)了一種具體算法 /// </summary> public class ConcreteStrategeB : Stratege { /// <summary> /// 具體算法 /// </summary> public override void Algorithm() { // 策略B中實現(xiàn)的算法 } } /// <summary> /// Context 上下文,維護一個對Stratege對象的引用 /// </summary> public class Context { private Stratege m_Stratege; /// <summary> /// 初始化上下文時,將具體策略傳入 /// </summary> /// <param name="stratege"></param> public Context(Stratege stratege) { m_Stratege = stratege; } /// <summary> /// 根據(jù)具體策略對象,調(diào)用其算法 /// </summary> public void ExecuteAlgorithm() { m_Stratege.Algorithm(); } }
4. 模式總結(jié)
4.1 優(yōu)點
4.1.1 策略模式是一種定義一系列算法的方法,從概念上來看,所有算法完成的都是相同的工作,只是實現(xiàn)不同,它可以以相同的方式調(diào)用所有的算法,減少了各種算法類與使用算法類之間的耦合。
4.1.2 策略模式的Stratege類為Context定義了一系列的可供重用的算法或行為。繼承有助于析取出這些算法的公共功能。
4.1.3 策略模式每個算法都有自己的類,可以通過自己的接口單獨測試。因而簡化了單元測試。
4.1.4 策略模式將具體算法或行為封裝到Stratege類中,可以在使用這些類中消除條件分支(避免了不同行為堆砌到一個類中)。
4.2 缺點
將選擇具體策略的職責(zé)交給了客戶端,并轉(zhuǎn)給Context對象
4.3 適用場景
4.3.1 當(dāng)實現(xiàn)某個功能需要有不同算法要求時
4.3.2 不同時間應(yīng)用不同的業(yè)務(wù)規(guī)則時
5. 實例:排序是我們經(jīng)常接觸到的算法,實現(xiàn)對一個數(shù)組的排序有很多方法,即可以采用不同的策略。下面給出了排序功能的策略模式的解決方案。
5.1 實現(xiàn)類圖
5.2 代碼實現(xiàn)
/// <summary> /// 排序算法策略 /// </summary> public abstract class SortStratege { /// <summary> /// 排序 /// </summary> /// <param name="array"></param> /// <returns></returns> public abstract int[] Sort(int[] array); } /// <summary> /// 冒泡排序 /// </summary> public class BubbleSort : SortStratege { /// <summary> /// 冒泡排序算法(遞增排序) /// </summary> /// <param name="array"></param> /// <returns></returns> public override int[] Sort(int[] array) { // 實現(xiàn)冒泡排序算法 for (int i = 0; i < array.Length; i++) { for (int j = i + 1; j < array.Length; j++) { if (array[i] > array[j]) { int temp = array[j]; array[j] = array[i]; array[i] = temp; } } } return array; } } /// <summary> /// 插入排序 /// </summary> public class InsertSort : SortStratege { /// <summary> /// 插入排序算法(遞增排序) /// </summary> /// <param name="array"></param> /// <returns></returns> public override int[] Sort(int[] array) { // 實現(xiàn)插入排序算法 int temp; int i, j, n; n = array.Length; for (i = 1; i < n; i++) { temp = array[i]; for (j = i; j > 0; j--) { if (temp < array[j - 1]) array[j] = array[j - 1]; else break; array[j] = temp; } } return null; } } public class SortContext { private int[] m_Array; private SortStratege m_Stratege; /// <summary> /// 初始化時將要排序的數(shù)組和排序策略傳入給Context /// </summary> /// <param name="array"></param> /// <param name="stratege"></param> public SortContext(int[] array, SortStratege stratege) { m_Array = array; m_Stratege = stratege; } /// <summary> /// 調(diào)用排序算法 /// </summary> /// <returns></returns> public int[] Sort() { int[] result = m_Stratege.Sort(this.m_Array); return result; } }
5.3 客戶端代碼
public class Program { public static void Main(Object[] args) { int[] array = new int[] { 12, 8, 9, 18, 22 }; //使用冒泡排序算法進行排序 SortStratege sortStratege = new BubbleSort(); SortContext sorter = new SortContext(array, sortStratege); int[] result = sorter.Sort(); //使用插入排序算法進行排序 SortStratege sortStratege2 = new InsertSort(); SortContext sorter2 = new SortContext(array, sortStratege2); int[] result2 = sorter.Sort(); } }
以上就是本文的全部內(nèi)容,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Quartz.Net任務(wù)和觸發(fā)器實現(xiàn)方法詳解
這篇文章主要介紹了Quartz.Net任務(wù)和觸發(fā)器實現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-12-12C#使用DevExpress中的SplashScreenManager控件實現(xiàn)啟動閃屏和等待信息窗口
這篇文章介紹了C#使用DevExpress中的SplashScreenManager控件實現(xiàn)啟動閃屏和等待信息窗口的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05C#實現(xiàn)向數(shù)組指定索引位置插入新的元素值
這篇文章給大家介紹了利用C#實現(xiàn)向數(shù)組指定索引位置插入新的元素值,首先需要定義一個一維數(shù)組,然后修改數(shù)組的長度,從而在其中增加一個元素,需要的朋友可以參考下2024-02-02