設計模式(6)---策略模式

  1、策略模式定義:算法

  策略模式(Strategy)定義了算法家族,分別封裝起來,讓它們之間能夠互相替換,此模式讓算法的變化不會影響到使用算法的客戶。ide

  分析:單元測試

  封裝的算法自己是一種策略,重要的是這些算法隨時可能互相替換的,這就是變化點,而封裝變化點是面向對象的一種重要的思惟方式。策略模式定義的這些算法完成的都是相同的工做,只是實現不一樣,它能夠以相同的方式調用全部的算法,減小了各類算法類與使用算法類之間的耦合。 測試

  

  2、UML類圖:this

  

  3、策略模式的基本代碼:  spa

class Program
    {
        static void Main(string[] args)
        {
            Contex context;

            context = new Contex(new ConcreteStrategyA());
            context.ContexInterface();

            context = new Contex(new ConcreteStrategyB());
            context.ContexInterface();

            Console.Read();
        }
    }

    abstract class Strategy
    {
        public abstract void AlgorithmInterface();
    }

    class ConcreteStrategyA : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("算法A實現");
        }
    }

    class ConcreteStrategyB : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("算法B實現");
        }
    }

    class ConcreteStrategyC : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("算法C實現");
        }
    }

    class Contex
    {
        Strategy strategy;

        public Contex(Strategy strategy)
        {
            this.strategy = strategy;
        }

        public void ContexInterface()
        {
            strategy.AlgorithmInterface();
        }
    }
View Code

 

  4、舉例說明:    設計

  功能:在一家商場有三種銷售方式:正常價格、打折銷售和返現銷售,設計一個收銀軟件,要求能知足上述的銷售方式。本例採用策略模式,將三種銷售方式封裝起來。code

  基本代碼: orm

abstract class CashSuper
    {
        public abstract double acceptCash(double money);
    }

    //正常價格
    class CashNormal : CashSuper
    {
        public override double acceptCash(double money)
        {
            return money;
        }
    }

    //打折策略
    class CashRebate : CashSuper
    {
        private double moneyRebate = 1d;

        public CashRebate(string moneyRebate)
        {
            this.moneyRebate = double.Parse(moneyRebate);
        }

        public override double acceptCash(double money)
        {
            return money * moneyRebate;
        }
    }

    //返現策略
    class CashReturn : CashSuper
    {
        private double moneyCondition = 0d;
        private double moneyReturn = 0d;

        public CashReturn(string moneyCondition, string moneyReturn)
        {
            this.moneyCondition = double.Parse(moneyCondition);
            this.moneyReturn = double.Parse(moneyReturn);
        }

        public override double acceptCash(double money)
        {
            double result = money;

            if (money >= moneyCondition)
            {
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;
            }

            return result;
        }
    }

    class CashContext
    {
        private CashSuper cashSuper;

        public CashContext(CashSuper cashSuper)
        {
            this.cashSuper = cashSuper;
        }

        public double GetResult(double money)
        {
            return cashSuper.acceptCash(money);
        }
    }
View Code

  調用方式: 對象

cashContext = new CashContext(new CashRebate("0.8"));
totalPrices = cashContext.GetResult(Convert.ToDouble(this.tbPrice.Text) * Convert.ToDouble(this.tbNumber.Text));

 

  5、策略模式和簡單工廠模式結合:

  結合後,實例化具體策略的過程由客戶端轉移到Context類中。修改後的CashContext: 

class CashContext
    {
        CashSuper cs = null;

        public CashContext(string type)
        {
            switch (type)
            {
                case "正常收費":
                    CashNormal cs0 = new CashNormal();
                    cs = cs0;
                    break;
                case "滿300返100":
                    CashReturn cs1 = new CashReturn("300", "100");
                    break;
                case "打八折":
                    CashRebate cs2 = new CashRebate("0.8");
                    cs = cs2;
                    break;
            }
        }

        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }
    }

  

  6、適用場景:

  一、在一個系統內有不少類,它們完成相同的功能僅在行爲上有所區別,策略模式能夠動態地選擇一種行爲。

  二、一個系統的算法使用的數據不讓客戶端獲取。策略模式能夠避免客戶端涉及到一些複雜的或特別的數據。

  三、若是一個對象有不少的行爲,若是不用恰當的模式,這些行爲就只好使用多重的條件選擇語句來實現。此時,使用策略模式,把這些行爲轉移到相應的具體策略類裏面,就能夠避免使用難以維護的多重條件選擇語句,並體現面向對象設計的概念。

  四、 一個系統須要動態地在幾種算法中選擇一種。那麼這些算法能夠包裝到一個個的具體算法類裏面,而這些具體算法類都是一個抽象算法類的子類。換言之,這些具體算法類均有統一的接口,因爲多態性原則,客戶端能夠選擇使用任何一個具體算法類,並只持有一個數據類型是抽象算法類的對象。

 

  7、策略模式優缺點:

  優勢:

  一、 簡化了單元測試,由於每一個算法都有本身的類,能夠經過本身的接口單獨測試。
  二、 定義了一系列的可供重用的算法或行爲。繼承有助於析取出這些算法中的公共功能。
      三、 遵照大部分GRASP原則和經常使用設計原則,高內聚、低偶合。 

  缺點:

  1. 客戶端必須知道全部的策略類,並自行決定使用哪個策略類。這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用於客戶端知道全部的算法或行爲的狀況。

  2. 策略模式形成不少的策略類。有時候能夠經過把依賴於環境的狀態保存到客戶端裏面,而將策略類設計成可共享的,這樣策略類實例能夠被不一樣客戶端使用。換言之,可使用享元模式來減小對象的數量。

相關文章
相關標籤/搜索