.Net行為型設(shè)計(jì)模式之策略模式(Stragety)
一、動(dòng)機(jī)(Motivate)
在軟件構(gòu)建過(guò)程中,某些對(duì)象使用的算法可能多種多樣,經(jīng)常改變,如果將這些算法都編碼到對(duì)象中,將會(huì)使對(duì)象變得異常復(fù)雜;而且有時(shí)候支持不使用的算法也是一個(gè)性能負(fù)擔(dān)。如何在運(yùn)行時(shí)根據(jù)需要透明地更改對(duì)象的算法?將算法與對(duì)象本身解耦,從而避免上述問(wèn)題?
二、意圖(Intent)
定義一系列算法,把它們一個(gè)個(gè)封裝起來(lái),并且使它們可互相替換。該模式使得算法可獨(dú)立于使用它的客戶(hù)而變化。 ——《設(shè)計(jì)模式》GoF
三、結(jié)構(gòu)圖(Structure)
四、模式的組成
可以看出,在策略模式的結(jié)構(gòu)圖有以下角色:
(1)、環(huán)境角色(Context):持有一個(gè)Strategy類(lèi)的引用。
需要使用ConcreteStrategy提供的算法。
內(nèi)部維護(hù)一個(gè)Strategy的實(shí)例。
負(fù)責(zé)動(dòng)態(tài)設(shè)置運(yùn)行時(shí)Strategy具體的實(shí)現(xiàn)算法。
負(fù)責(zé)跟Strategy之間的交互和數(shù)據(jù)傳遞
(2)、抽象策略角色(Strategy):定義了一個(gè)公共接口,各種不同的算法以不同的方式實(shí)現(xiàn)這個(gè)接口,Context使用這個(gè)接口調(diào)用不同的算法,一般使用接口或抽象類(lèi)實(shí)現(xiàn)。
(3)、具體策略角色(ConcreteStrategy):實(shí)現(xiàn)了Strategy定義的接口,提供具體的算法實(shí)現(xiàn)。
五、策略模式的代碼實(shí)現(xiàn)
在現(xiàn)實(shí)生活中,策略模式的例子也是很多的,例如:一個(gè)公司會(huì)有很多工作種類(lèi),每個(gè)工作種類(lèi)負(fù)責(zé)的工作不同,自然每個(gè)工種的工資計(jì)算方法也會(huì)有千差萬(wàn)別,我們今天就以工資的計(jì)算為例來(lái)說(shuō)明策略模式的使用,我們直接上代碼,但是實(shí)際編碼中切記別這樣,我們要通過(guò)迭代的方式使用模式。實(shí)現(xiàn)代碼如下:
public static void Main(String[] args) { //普通員工的工資 SalaryContext context = new SalaryContext(new NormalPeopleSalary()); context.GetSalary(3000); //CEO的工資 context.ISalaryStrategy = new CEOSalary(); context.GetSalary(6000); Console.Read(); } //環(huán)境角色---相當(dāng)于Context類(lèi)型 public sealed class SalaryContext { private ISalaryStrategy _strategy; public SalaryContext(ISalaryStrategy strategy) { this._strategy = strategy; } public ISalaryStrategy ISalaryStrategy { get { return _strategy; } set { _strategy = value; } } public void GetSalary(double income) { _strategy.CalculateSalary(income); } } //抽象策略角色---相當(dāng)于Strategy類(lèi)型 public interface ISalaryStrategy { //工資計(jì)算 void CalculateSalary(double income); } //程序員的工資--相當(dāng)于具體策略角色ConcreteStrategyA public sealed class ProgrammerSalary : ISalaryStrategy { public void CalculateSalary(double income) { Console.WriteLine("我的工資是:基本工資(" + income + ")底薪(" + 8000 + ")+加班費(fèi)+項(xiàng)目獎(jiǎng)金(10%)"); } } //普通員工的工資---相當(dāng)于具體策略角色ConcreteStrategyB public sealed class NormalPeopleSalary : ISalaryStrategy { public void CalculateSalary(double income) { Console.WriteLine("我的工資是:基本工資(" + income + ")底薪(3000)+加班費(fèi)"); } } //CEO的工資---相當(dāng)于具體策略角色ConcreteStrategyC public sealed class CEOSalary : ISalaryStrategy { public void CalculateSalary(double income) { Console.WriteLine("我的工資是:基本工資(" + income + ")底薪(20000)+項(xiàng)目獎(jiǎng)金(20%)+公司股票"); } }
六、策略模式的實(shí)現(xiàn)要點(diǎn):
Strategy及其子類(lèi)為組件提供了一系列可重用的算法,從而可以使得類(lèi)型在運(yùn)行時(shí)方便地根據(jù)需要在各個(gè)算法之間進(jìn)行切換,所謂封裝算法,支持算法的變化。Strategy模式提供了用條件判斷語(yǔ)句以外的另一種選擇,消除條件判斷語(yǔ)句,就是在解耦合。含有許多條件判斷語(yǔ)句的代碼通常都需要Strategy模式。
與State類(lèi)似,如果Strategy對(duì)象沒(méi)有實(shí)例變量,那么各個(gè)上下文可以共享一個(gè)Strategy對(duì)象,從而節(jié)省對(duì)象開(kāi)銷(xiāo)。Strategy模式適用的是算法結(jié)構(gòu)中整個(gè)算法的改變,而不是算法中某個(gè)部分的改變。
- Template Method方法:執(zhí)行算法的步驟協(xié)議是本身放在抽象類(lèi)里面的,允許一個(gè)通用的算法操作多個(gè)可能實(shí)現(xiàn)
- Strategy模式:執(zhí)行算法的協(xié)議是在具體類(lèi),每個(gè)具體實(shí)現(xiàn)有不同通用算法來(lái)做。
1、策略模式的主要優(yōu)點(diǎn)有:
1】、策略類(lèi)之間可以自由切換。由于策略類(lèi)都實(shí)現(xiàn)同一個(gè)接口,所以使它們之間可以自由切換。
2】、易于擴(kuò)展。增加一個(gè)新的策略只需要添加一個(gè)具體的策略類(lèi)即可,基本不需要改變?cè)械拇a。
3】、避免使用多重條件選擇語(yǔ)句,充分體現(xiàn)面向?qū)ο笤O(shè)計(jì)思想。
2、策略模式的主要缺點(diǎn)有:
1】、客戶(hù)端必須知道所有的策略類(lèi),并自行決定使用哪一個(gè)策略類(lèi)。這點(diǎn)可以考慮使用IOC容器和依賴(lài)注入的方式來(lái)解決,關(guān)于IOC容器和依賴(lài)注入(Dependency Inject)的文章可以參考:IoC 容器和Dependency Injection 模式。
2】、策略模式會(huì)造成很多的策略類(lèi)。
3、在下面的情況下可以考慮使用策略模式:
1】、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種的情況下。那么這些算法可以包裝到一個(gè)個(gè)具體的算法類(lèi)里面,并為這些具體的算法類(lèi)提供一個(gè)統(tǒng)一的接口。
2】、如果一個(gè)對(duì)象有很多的行為,如果不使用合適的模式,這些行為就只好使用多重的if-else語(yǔ)句來(lái)實(shí)現(xiàn),此時(shí),可以使用策略模式,把這些行為轉(zhuǎn)移到相應(yīng)的具體策略類(lèi)里面,就可以避免使用難以維護(hù)的多重條件選擇語(yǔ)句,并體現(xiàn)面向?qū)ο笊婕暗母拍睢?/p>
七、.NET 策略模式的實(shí)現(xiàn)
在.NET Framework中也不乏策略模式的應(yīng)用例子。例如,在.NET中,為集合類(lèi)型ArrayList和List<T>提供的排序功能,其中實(shí)現(xiàn)就利用了策略模式,定義了IComparer接口來(lái)對(duì)比較算法進(jìn)行封裝,實(shí)現(xiàn)IComparer接口的類(lèi)可以是順序,或逆序地比較兩個(gè)對(duì)象的大小,具體.NET中的實(shí)現(xiàn)可以使用反編譯工具查看List<T>.Sort(IComparer<T>)的實(shí)現(xiàn)。其中List<T>就是承擔(dān)著環(huán)境角色,而IComparer<T>接口承擔(dān)著抽象策略角色,具體的策略角色就是實(shí)現(xiàn)了IComparer<T>接口的類(lèi),List<T>類(lèi)本身實(shí)現(xiàn)了存在實(shí)現(xiàn)了該接口的類(lèi),我們可以自定義繼承與該接口的具體策略類(lèi)。
到此這篇關(guān)于.Net行為型設(shè)計(jì)模式之策略模式(Stragety)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- .Net行為型設(shè)計(jì)模式之備忘錄模式(Memento)
- .Net行為型設(shè)計(jì)模式之訪問(wèn)者模式(Visitor)
- .Net行為型設(shè)計(jì)模式之職責(zé)鏈模式(Chain of Responsibility)
- .Net行為型設(shè)計(jì)模式之狀態(tài)模式(State)
- .Net行為型設(shè)計(jì)模式之中介者模式(Mediator)
- .Net行為型設(shè)計(jì)模式之觀察者模式(Observer)
- .Net行為型設(shè)計(jì)模式之迭代器模式(Iterator)
- .Net行為型設(shè)計(jì)模式之命令模式(Command)
- .Net行為型設(shè)計(jì)模式之模板方法模式(Template?Method)
- .Net行為型設(shè)計(jì)模式之解釋器模式(Interpreter)
相關(guān)文章
c#中實(shí)現(xiàn)文件拖放打開(kāi)的方法
向ListBox拖入一個(gè)文件,ListBox顯示該文件的路徑,然后單擊該路徑,點(diǎn)擊Open按鈕打開(kāi)該文件2006-10-10.NET?6更新使.NET生態(tài)系統(tǒng)蛻變
微軟正式發(fā)布.NET最新長(zhǎng)期支持版本.NET?6,這個(gè)版本的更新重點(diǎn),除了C#和F#都有許多語(yǔ)言功能改進(jìn)之外,.NET?6終于集大成,成為跨瀏覽器、云計(jì)算、桌面、物聯(lián)網(wǎng)和移動(dòng)應(yīng)用程序的統(tǒng)一平臺(tái),性能也獲得大幅提升,并且更完整支持Arm642022-01-01.Net創(chuàng)建型設(shè)計(jì)模式之工廠方法模式(Factory?Method)
這篇文章介紹了.Net設(shè)計(jì)模式之工廠方法模式(Factory?Method),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05為大家經(jīng)常為md5加密過(guò)的常用admin,admin888,0000密碼
為大家經(jīng)常為md5加密過(guò)的常用admin,admin888,0000密碼...2007-10-10.Net行為型設(shè)計(jì)模式之中介者模式(Mediator)
這篇文章介紹了.Net行為型設(shè)計(jì)模式之中介者模式(Mediator),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05ASP.NET創(chuàng)建三層架構(gòu)圖解詳細(xì)教程
本文以圖片的形式完整演示了創(chuàng)建三層架構(gòu)的完整步驟,簡(jiǎn)單實(shí)用,希望能給大家一些幫助。2016-04-04