1. 程式人生 > >大話設計模式學習筆記-策略模式

大話設計模式學習筆記-策略模式

策略模式

它定義了演算法家族,分別封裝起來,讓他們之間可以互相替換,此模式讓演算法的變化不會影響到使用演算法的客戶。

優點

策略模式是一種定義了一系列演算法的方法,從個概念上看,所有這些演算法完成的都是相同的工作。只是實現不同。他可以以相同的方式呼叫所有的演算法,減少了各種演算法類與使用演算法類之間的耦合。

策略模式優化了單元測試,因為每個演算法都有自己的類,可以通過自己的介面單獨測試。

不足

策略模式就是用來封裝演算法的,選擇具體實現的職責由客戶端物件承擔,並轉給策略模式的Context物件,這本身並沒有接觸客戶端需要選擇判斷的壓力。不過和簡單工廠模式結合後,選擇具體實現的職責也可以由Context來承擔。


策略模式結構演示

父類:Strategy

定義所有支援的演算法的公共介面,為Context定義了一系列的可重用的演算法或行為,繼承有助於析取出這些演算法中的公共功能。

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

子類:ConcreteStrategy

封裝了具體的演算法或行為,繼承Strategy

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實現"); } }

上下文類:Context

用一個ConcreteStrategy來配置,維護一個對Strategy物件的引用

class Context{
    Strategy strategy;
    //初始化物件
    public Context(Strategy strategy)=>this.strategy=strategy;
    //呼叫具體的策略
    public void ContextInterface()=>strategy.AlgorithmInterface();
}

測試類:Program

class Program{
    static void Main(string[] args){
        Context context;
        context = new Context(new ConcreteStrategyA());
        context.ContextInterface();
        context = new Context(new ConcreteStrategyB());
        context.ContextInterface();
        context = new Context(new ConcreteStrategyC());
        context.ContextInterface();
        Console.Read();
    }
}

測試結果:控制檯

演算法A實現
演算法B實現
演算法C實現

使用策略模式改進商場促銷

上下文類:CashContext

增加上下文類。通過呼叫上下文類,傳入上下文類不同的策略來實現不同的演算法或行為

class CashContext{
    private CashSuper cs;
    public CashContext(CashSuper csuper) => cs = csuper;
    public double GetResult(double money) => cs.AcceptCash(money);
}

測試類:Program

修改測試類

class Program
{
    static void Main(string[] args){
        Console.Write("請輸入商品單價:");
        double foodSprice=double.Parse(Console.ReadLine());
        Console.Write("請輸入商品數量:");
        double fooeNum = double.Parse(Console.ReadLine());
        Console.WriteLine($"1:原價{Environment.NewLine}2:八折{Environment.NewLine}3:滿300返100");
        Console.Write("請選擇優惠方式:");
        CashContext cc = null;
        switch (Console.ReadLine()){
            case "1":
                cc = new CashContext(new CashNormal());
                break;
            case "2":
                cc = new CashContext(new CashRebate(0.8));
                break;
            case "3":
                cc = new CashContext(new CashReturn(300,100));
                break;
        }
        Console.WriteLine(cc.GetResult(foodSprice*fooeNum));
        Console.ReadKey();
    }
}

使用策略模式和簡單工廠模式結合改進商場促銷

策略模式和簡單工廠模式的結合,使客戶端只需要認識一個上下文類即可,降低耦合性。

雖然Context裡還是用到了switch,但是可以使用反射技術解決,在抽象工廠模式中對此有詳細講解。

上下文類:CashContext

改進CashContext,將演算法的選擇在上下文類構造方法中完成,建立好對應的例項。

class CashContext
{
    private CashSuper cs;
    public CashContext(string type){
        switch (type){
            case "1":
                cs = new CashNormal();
                break;
            case "2":
                cs = new CashRebate(0.8);
                break;
            case "3":
                cs = new CashReturn(300, 100);
                break;
        }
    }
    public double GetResult(double money) => cs.AcceptCash(money);
}

測試類:Program

將具體的收費演算法與客戶端徹底分離,更加簡潔明瞭。

class Program{
    static void Main(string[] args){
        Console.Write("請輸入商品單價:");
        double foodSprice=double.Parse(Console.ReadLine());
        Console.Write("請輸入商品數量:");
        double fooeNum = double.Parse(Console.ReadLine());
        Console.WriteLine($"1:原價{Environment.NewLine}2:八折{Environment.NewLine}3:滿300返100");
        Console.Write("請選擇優惠方式:");
        var csuper = new CashContext(Console.ReadLine());
        Console.WriteLine(csuper.GetResult(foodSprice*fooeNum));
        Console.ReadKey();
    }
}