策略模式(Strategy):
策略模式是對演算法的包裝,是把使用演算法的責任和演算法本身分割開來,委派給不同的物件管理,策略模式通常把一個系列的演算法包裝到一系列的策略類里面,作為一個抽象策略類的子類,用一句話來說,就是:“準備一組演算法,并將每一個演算法封裝起來,使得它們可以互換”,
策略模式的角色:

1)環境類(Context):采用組合或聚合的方式維護一個對Strategy物件的參考,
2)抽象策略類(Strategy):定義所有支持的演算法的公共介面,Context使用這個介面來呼叫某ConcreteStrategy定義的演算法,
3)具體策略類(ConcreteStrategy):實作Strategy介面,
案例:
某商場銷售系統采用三種收費邏輯:正常收費;返現收費(滿300返20);打折收費(打8折),
1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 CashContext cashContext = new CashContext(new CashNormal()); 6 Console.WriteLine(cashContext.GetResult(200)); 7 CashContext cashContext2 = new CashContext(new CashRebate(0.8)); 8 Console.WriteLine(cashContext2.GetResult(200)); 9 CashContext cashContext3 = new CashContext(new CashReturn(300, 20));10 Console.WriteLine(cashContext3.GetResult(300));11 }12 }13 14 /// <summary>15 /// 環境類Context16 /// </summary>17 public class CashContext18 {19 private CashSuper cs;20 21 public CashContext(CashSuper cashSuper)22 {23 this.cs = cashSuper;24 }25 26 public double GetResult(double money)27 {28 if (cs != null)29 {30 return cs.AcceptCash(money);31 }32 return 0;33 }34 }35 36 /// <summary>37 /// 收費系統,相當于Strategy38 /// </summary>39 public interface CashSuper40 {41 double AcceptCash(double money);42 }43 44 /// <summary>45 /// 正常收費46 /// </summary>47 public class CashNormal : CashSuper48 {49 public double AcceptCash(double money)50 {51 return money;52 }53 }54 55 /// <summary>56 /// 打折收費57 /// </summary>58 public class CashRebate : CashSuper59 {60 private double moneyRebate = 1d;61 62 public CashRebate(double moneyRebate)63 {64 this.moneyRebate = moneyRebate;65 }66 67 public double AcceptCash(double money)68 {69 return money * moneyRebate;70 }71 }72 73 /// <summary>74 /// 返現收費75 /// </summary>76 public class CashReturn : CashSuper77 {78 private double moneyCondition = 0.0d;79 private double moneyReturn = 0.0d;80 81 public CashReturn(double moneyCondition, double moneyReturn)82 {83 this.moneyCondition = moneyCondition;84 this.moneyReturn = moneyReturn;85 }86 87 public double AcceptCash(double money)88 {89 double result = money;90 if (money >= moneyCondition)91 result = money - Math.Floor(money / moneyCondition) * moneyReturn;92 return result;93 }94 }
策略模式的優缺點:
優點:
1)策略模式提供了管理相關的演算法族的辦法,策略類的等級結構定義了一個演算法或行為族,恰當使用繼承可以把公共的代碼轉移到父類里面,從而避免重復的代碼,
2)策略模式提供了可以替換繼承關系的辦法,繼承可以處理多種演算法或行為,如果不是用策略模式,那么使用演算法或行為的環境類就可能會有一些子類,每一個子類提供一個不同的演算法或行為,但是,這樣一來演算法或行為的使用者就和演算法或行為本身混在一起,決定使用哪一種演算法或采取哪一種行為的邏輯就和演算法或行為的邏輯混合在一起,從而不可能再獨立演化,繼承使得動態改變演算法或行為變得不可能,
3)使用策略模式可以避免使用多重條件轉移陳述句,多重轉移陳述句不易維護,它把采取哪一種演算法或采取哪一種行為的邏輯與演算法或行為的邏輯混合在一起,統統列在一個多重轉移陳述句里面,比使用繼承的辦法還要原始和落后,
缺點:
1)客戶端必須知道所有的策略類,并自行決定使用哪一個策略類,這就意味著客戶端必須理解這些演算法的區別,以便適時選擇恰當的演算法類,換言之,策略模式只適用于客戶端知道所有的演算法或行為的情況,
2)策略模式造成很多的策略類,每個具體策略類都會產生一個新類,有時候可以通過把依賴于環境的狀態保存到客戶端里面,而將策略類設計成可共享的,這樣策略類實體可以被不同客戶端使用,換言之,可以使用享元模式來減少物件的數量,
策略模式的應用場景:
1)一個系統需要動態地在幾種演算法中選擇一種時,可將每個演算法封裝到策略類中,
2)一個類定義了多種行為,并且這些行為在這個類的操作中以多個條件陳述句的形式出現,可將每個條件分支移入它們各自的策略類中以代替這些條件陳述句,
3)系統中各演算法彼此完全獨立,且要求對客戶隱藏具體演算法的實作細節時,
4)系統要求使用演算法的客戶不應該知道其操作的資料時,可使用策略模式來隱藏與演算法相關的資料結構,
5)多個類只區別在表現行為不同,可以使用策略模式,在運行時動態選擇具體要執行的行為,
策略模式與工廠模式的區別?
從結構上看,策略模式和工廠模式都是子類繼承抽象父類,通過傳入引數到容器類(工廠模式的factory類,策略模式的Content類),選擇對應的類進行行為操作,但是我們都知道工廠模式是創建型設計模式,而策略模式則是行為型設計模式,那兩者到底有什么區別呢?
1)工廠模式是用來創建物件,策略模式是讓一個物件在許多行為中選擇一種行為,
2)關注點不一樣,一個關注物件的創建,一個關注的是行為封裝,
3)解決不同的問題:工廠模式是創建型的設計模式,它接受指令,創建出符合要求的實體;它主要解決的是資源的統一分發,將物件的創建完全獨立出來,讓物件的創建和具體的使用客戶無關,主要應用在多資料庫選擇,類別庫檔案加載等,策略模式是為了解決的是策略的切換與擴展,更簡潔的說是定義策略族,分別封裝起來,讓他們之間可以相互替換,策略模式讓策略的變化獨立于使用策略的客戶,
4)工廠相當于黑盒子,策略相當于白盒子,
策略模式與橋接模式的區別?
在橋接模式中,Abstraction通過聚合的方式參考Implementor,策略模式中,Context也使用聚合的方式參考Strategy抽象介面,從兩者的結構圖可以看出,在這兩種模式中,都存在一個物件使用聚合的方式參考另一個物件的抽象介面的情況,而且該抽象介面的實作可以有多種并且可以替換,可以說兩者在表象上都是呼叫者與被呼叫者之間的解耦,以及抽象介面與實作的分離,但兩者存在一定的區別:
1)在形式上,在橋接模式中不僅Implementor具有變化(ConcreateImplementior),而且Abstraction也可以發生變化(RefinedAbstraction),而且兩者的變化是完全獨立的,RefinedAbstraction與ConcreateImplementior之間松散耦合,它們僅僅通過Abstraction與Implementor之間的關系聯系起來,而在策略模式中,并不考慮Context的變化,只有演算法的可替代性,
2)在語意上,橋接模式強調Implementor介面僅提供基本操作,而Abstraction則基于這些基本操作定義更高層次的操作,而策略模式強調Strategy抽象介面的提供的是一種演算法,一般是無狀態、無資料的,而Context則簡單呼叫這些演算法完成其操作,
3)橋接模式中不僅定義Implementor的介面而且定義Abstraction的介面,Abstraction的介面不僅僅是為了與Implementor通信而存在的,這也反映了結構型模式的特點:通過繼承、聚合的方式組合類和物件以形成更大的結構,在策略模式中,Startegy和Context的介面都是兩者之間的協作介面,并不涉及到其它的功能介面,所以它是行為模式的一種,行為模式的主要特點就是處理的是物件之間的通信方式,往往是通過引入中介者物件將通信雙方解耦,在這里實際上就是將Context與實際的演算法提供者解耦,
所以相對策略模式,橋接模式要表達的內容要更多,結構也更加復雜,橋接模式表達的主要意義其實是介面隔離的原則,即把本質上并不內聚的兩種體系區別開來,使得它們可以松散的組合,而策略在解耦上還僅僅是某一個演算法的層次,沒有到體系這一層次,從結構圖中可以看到,策略的結構是包容在橋接結構中的,橋接中必然存在著策略模式,Abstraction與Implementor之間就可以認為是策略模式,但是橋接模式一般Implementor將提供一系列的成體系的操作,而且Implementor是具有狀態和資料的靜態結構,而且橋接模式Abstraction也可以獨立變化,
參考:https://blog.csdn.net/donnie88888888/article/details/52751328
https://blog.csdn.net/basycia/article/details/50478245
http://www.blogjava.net/wangle/archive/2007/04/25/113545.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/42110.html
標籤:設計模式
上一篇:命令模式
下一篇:創建型設計模式(上)
