[.net 面向對象程序設計深刻](26)實戰設計模式——策略模式 Strategy (行爲型)html
策略模式定義了一系列的算法,並將每個算法封裝起來,並且使它們還能夠相互替換。策略模式讓算法獨立於使用它的客戶而獨立變化。git
策略模式的組成: github
(1)多個相關的類中,僅行爲不一樣,即一個系統中須要在幾個不一樣的算法中選擇時。好比中出行中,咱們選擇交通方式火車、飛機、自行車、汽車等。算法
(2)一個算法的不一樣變體時。好比一個收取暖費的算法,不一樣的收費方式如按房屋面積、按供熱焦耳量、按面積和熱量混合法等 。編程
(3)不想暴露算法給使用者。好比,有一個複雜算法或算法中有相對應的數據結構不想讓使用者知道。設計模式
(4)一個行爲中有多個條件時。好比,有多個條件語句,並且實現比較複雜或比較長時,使用策略模式,除告終構清晰外,維護某一分支也比較方便。數據結構
(1)抽象策略類和具體策略角色爲環境類定義了一系列能夠重用的算法或行爲,而且繼承有助於取出共用部分的算法。ide
(2)提供了能夠替換繼承關係的辦法。能夠建立一個環境類的子類,裏面封裝不一樣的行爲,經過環境類來驅動策略。但這樣也會致使環境類中的行爲包含了具體實現,使用程序難以理解,難以維護。post
(3)消除了複雜的IF..ELSE。含有許多複雜條件語句的代碼可使用策略模式來使邏輯更加清晰,易於維護。this
(4)實了具備相同類型的多個行業的切換。讓用戶在多個策略中切換行爲。
(1)須要事先知道全部策略類行爲有何不一樣,才能讓用戶很好的選擇。容易向使用者暴露策略中的各個行爲。
(2)環境類和策略類之間產生通訊開銷。
(3)須要建立不少策略類。後面會說到享元模式,必定程度上減小類。
(1)華山論劍
仍是以熟悉的華山論劍爲例,比賽方式(也就是三個具體策略類)有「比外功、比內功、比招式」,場景爲「華山」(也就是場景類HuaShan),開始比賽了,主持人事先知道這幾種比賽方式(也就是具體策略類),主持人(也就是具體使用者)讓依次以這幾種方式進行。
先看一下UML類圖(在VS中使用類圖,能夠參考我前面的文章:在Visual Studio 2013/2015中設計UML類圖)
下面是具體代碼:
抽象策略類 LunJian
public abstract class LunJian { public abstract void BiSai(); }
具體策略類 WaiGong NeiGong ZhaoShi
public class WaiGong : LunJian { public override void BiSai() { Console.WriteLine("外功比試開始了!"); } }
public class NeiGong : LunJian { public override void BiSai() { Console.WriteLine("內功比試開始了!"); } }
public class ZhaoShi : LunJian { public override void BiSai() { Console.WriteLine("招式比試開始了!"); } }
場景類(也就是策略上下文 ) HuaShan
public class HuaShan { LunJian lunJian=null; public void SetLunJian(LunJian lunJian) { this.lunJian = lunJian; } public void BiShi() { this.lunJian.BiSai(); } }
使用者,就是控制檯應用程序
class Program { static void Main(string[] args) { HuaShan huanShan = new HuaShan(); huanShan.SetLunJian(new WaiGong()); huanShan.BiShi(); huanShan.SetLunJian(new NeiGong()); huanShan.BiShi(); huanShan.SetLunJian(new ZhaoShi()); huanShan.BiShi(); Console.ReadLine(); } }
依次給出三種比試方式策略,運行結果以下:
(2)華山論劍升級版
上面的示例比較簡單,假如咱們比試開始的時候,還須要點名兩個比賽選手,這就須要在具體策略類的方法中增長參數。咱們增長BiShi()方法參數,改進後代碼以下:
抽象策略類 LunJian
public abstract class LunJian { public abstract void BiSai(string player1,string player2); }
具體策略類 WaiGong NeiGong ZhaoShi
public class WaiGong : LunJian { public override void BiSai(string player1,string player2) { Console.WriteLine("外功比試開始了!"+string.Format(" {0} 和 {1} 出場",player1,player2)); } }
public class NeiGong : LunJian { public override void BiSai(string player1, string player2) { Console.WriteLine("內功比試開始了!" + string.Format(" {0} 和 {1} 出場", player1, player2)); } }
public class ZhaoShi : LunJian { public override void BiSai(string player1, string player2) { Console.WriteLine("招式比試開始了!" + string.Format(" {0} 和 {1} 出場", player1, player2)); } }
場景類(也就是策略上下文 ) HuaShan
public class HuaShan { LunJian lunJian=null; public void SetLunJian(LunJian lunJian) { this.lunJian = lunJian; } public void BiShi(string player1,string player2) { this.lunJian.BiSai(player1,player2); } }
使用者,就是控制檯應用程序
class Program { static void Main(string[] args) { HuaShan huanShan = new HuaShan(); huanShan.SetLunJian(new WaiGong()); huanShan.BiShi("黃藥師","歐陽鋒"); huanShan.SetLunJian(new NeiGong()); huanShan.BiShi("洪七公","一燈大師"); huanShan.SetLunJian(new ZhaoShi()); huanShan.BiShi("歐陽鋒","洪七公"); Console.ReadLine(); } }
運行結果:
華山論劍的業務確定比這個要複雜,上面的出場人不一樣,比賽方式不一樣,甚至還其餘不一樣的規則出現。
若是咱們不使用策略模式,而經過傳統的if...else來寫,不但要寫很長的代碼,還須要條件語句屢次嵌套。
最主要的是代碼的可讀性較差,並且難以再解。
(1)策略模式是一個比較容易理解和使用的設計模式,策略模式是對算法的封裝,它把算法的責任和算法自己分割開,委派給不一樣的對象管理。策略模式一般把一個系列的算法封裝到一系列的策略類裏面,做爲一個抽象策略類的子類。用一句話來講,就是「準備一組算法,並將每個算法封裝起來,使得它們能夠互換」。
(2)在策略模式中,應當由客戶端本身決定在什麼狀況下使用什麼具體策略角色。
(3)策略模式僅僅封裝算法,提供新算法插入到已有系統中,以及老算法從系統中「退休」的方便,策略模式並不決定在什麼時候使用何種算法,算法的選擇由客戶端來決定。這在必定程度上提升了系統的靈活性,可是客戶端須要理解全部具體策略類之間的區別,以便選擇合適的算法,這也是策略模式的缺點之一,在必定程度上增長了客戶端的使用難度。
https://github.com/yubinfeng/BlogExamples.git
==============================================================================================
<若是對你有幫助,記得點一下推薦哦,若有有不明白或錯誤之處,請多交流>
<對本系列文章閱讀有困難的朋友,請先看 《.net 面向對象編程基礎》 和 《.net 面向對象程序設計進階》 >
<轉載聲明:技術須要共享精神,歡迎轉載本博客中的文章,但請註明版權及URL>
==============================================================================================