1、引言html
本文要介紹的策略模式也就是對策略進行抽象,策略的意思就是方法,因此也就是對方法的抽象,下面具體分享下我對策略模式的理解。算法
2、策略者模式介紹工具
2.1 策略模式的定義this
在現實生活中,策略模式的例子也很是常見。例如,中國的所得稅,分爲企業所得稅、外商投資企業或外商企業所得稅和我的所得稅。針對於這3種所得稅,所計算的方式不一樣。我的所得稅有我的所得稅的計算方式,而企業所得稅有其對應計算方式。若是不採用策略模式來實現這樣一個需求的話,可能咱們會定義一個所得稅類,該類有一個屬性來標識所得稅的類型,而且有一個計算稅收的CalculateTax()方法,在該方法體內須要對稅收類型進行判斷,經過if-else語句來針對不一樣的稅收類型來計算其所得稅。這樣的實現確實能夠解決這個場景嗎,可是這樣的設計不利於擴展。若是系統後期須要增長一種所得稅時,此時不得不回去修改CalculateTax方法來多添加一個判斷語句,這樣明白違背了「開放——封閉」原則。此時,咱們能夠考慮使用策略模式來解決這個問題,既然稅收方法是這個場景中的變化部分,此時天然能夠想到對稅收方法進行抽象。具體的實現代碼見2.3部分。spa
前面介紹了策略模式用來解決的問題,下面具體給出策略的定義。策略模式是針對一組算法,將每一個算法封裝到具備公共接口的獨立的類中,從而使它們能夠相互替換。策略模式使得算法能夠在不影響到客戶端的狀況下發生變化。設計
2.2 策略模式的結構rest
策略模式是對算法的包裝,是把使用算法的責任和算法自己分割開,委派給不一樣的對象負責。策略模式一般把一系列的算法包裝到一系列的策略類裏面。用一句話慨括策略模式就是——「將每一個算法封裝到不一樣的策略類中,使得它們能夠互換」。code
下面是策略模式的結構圖:htm
該模式涉及到三個角色:對象
1)環境角色(Context):持有一個Strategy類的引用;
2)抽象策略角色(Strategy):這是一個抽象角色,一般由一個接口或抽象類來實現。此角色給出全部具體策略類所需實現的接口。
3)具體策略角色(ConcreteStrategy):包裝了相關算法或行爲。
2.3 策略模式的實現
下面就以所得稅的例子來實現下策略模式,具體實現代碼以下所示:
namespace StrategyPattern { // 所得稅計算策略 public interface ITaxStragety { double CalculateTax(double income); } // 我的所得稅 public class PersonalTaxStrategy : ITaxStragety { public double CalculateTax(double income) { return income * 0.12; } } // 企業所得稅 public class EnterpriseTaxStrategy : ITaxStragety { public double CalculateTax(double income) { return (income - 3500) > 0 ? (income - 3500) * 0.045 : 0.0; } } public class InterestOperation { private ITaxStragety m_strategy; public InterestOperation(ITaxStragety strategy) { this.m_strategy = strategy; } public double GetTax(double income) { return m_strategy.CalculateTax(income); } } class App { static void Main(string[] args) { // 我的所得稅方式 InterestOperation operation = new InterestOperation(new PersonalTaxStrategy()); Console.WriteLine("我的支付的稅爲:{0}", operation.GetTax(5000.00)); // 企業所得稅 operation = new InterestOperation(new EnterpriseTaxStrategy()); Console.WriteLine("企業支付的稅爲:{0}", operation.GetTax(50000.00)); Console.Read(); } } }
3、策略者模式在.NET中應用
在.NET Framework中也不乏策略模式的應用例子。例如,在.NET中,爲集合類型ArrayList和List<T>提供的排序功能,其中實現就利用了策略模式。定義了IComparer接口來對比較算法進行封裝,實現IComparer接口的類能夠是順序或逆序地比較兩個對象的大小。具體.NET中的實現可使用反編譯工具查看List<T>.Sort(IComparer<T>)的實現。其中List<T>就是承擔着環境角色,而IComparer<T>接口承擔着抽象策略角色,具體的策略角色就是實現了IComparer<T>接口的類,List<T>類自己實現了該接口的類,咱們能夠自定義繼承與該接口的具體策略類。
4、策略者模式的適用場景
在下面的狀況下能夠考慮使用策略模式:
1)一個系統須要動態地在幾種算法中選擇一種的狀況下。那麼這些算法能夠包裝到一個個具體的算法類裏面,併爲這些具體的算法類提供一個統一的接口。
2)若是一個對象有不少的行爲,若不使用合適的模式,這些行爲就只好使用多重的if-else語句來實現。此時,可使用策略模式,把這些行爲轉移到相應的具體策略類裏面,就能夠避免使用難以維護的多重條件選擇語句,並體現面向對象涉及的概念。
5、策略者模式的優缺點
策略模式的主要優勢有:
1)策略類之間能夠自由切換。因爲策略類都實現同一個接口,因此使它們之間能夠自由切換。
2)易於擴展。增長一個新的策略只須要添加一個具體的策略類便可,基本不須要改變原有的代碼。
3)避免使用多重條件選擇語句,充分體現面向對象設計思想。
策略模式的主要缺點有:
1)客戶端必須知道全部的策略類,並自行決定使用哪個策略類。這點能夠考慮使用IOC容器和依賴注入的方式來解決。
2)策略模式會形成不少的策略類。
6、總結
到這裏,策略模式的介紹就結束了,策略模式主要是對方法的封裝,把一系列方法封裝到一系列的策略類中,從而使不一樣的策略類能夠自由切換,並避免在系統使用多重條件選擇語句來選擇針對不一樣狀況來選擇不一樣的方法。