16_策略模式

野码發表於2024-03-14

策略模式是一種行為型設計模式,它定義了一系列的演算法,並將每個演算法封裝到獨立的類中,使它們可以互相替換。策略模式使得演算法可以獨立於客戶端而變化,客戶端可以根據需要選擇不同的演算法。

策略模式有三個主要角色:

  1. 環境類(Context):它持有一個策略物件的引用,並在需要的時候呼叫策略物件的方法。環境類可以根據需要動態地替換策略物件。

  2. 抽象策略類(Strategy):定義了策略的抽象介面,通常包含一個或多個策略方法。

  3. 具體策略類(Concrete Strategy):實現了抽象策略介面,提供具體的演算法實現。

策略模式的工作原理如下:

  1. 環境類持有一個策略物件的引用,並在需要的時候呼叫策略物件的方法。

  2. 客戶端根據需要選擇具體的策略類,並將其傳遞給環境類。

  3. 環境類根據傳入的策略物件,呼叫相應的策略方法。

策略模式的優點包括:

  1. 提供了一種簡潔的方式來封裝和切換演算法,使得演算法可以獨立於客戶端變化。

  2. 可以避免使用大量的條件判斷語句,提高了程式碼的可讀性和可維護性。

  3. 可以透過繼承和介面的方式擴充套件新的策略類。

策略模式適用於以下場景:

  1. 當多個類只有在演算法或行為上有不同的情況下,可以使用策略模式。

  2. 當需要在執行時動態地選擇不同的演算法時,可以使用策略模式。

總結而言,策略模式透過將演算法封裝到獨立的策略類中,使得演算法可以獨立於客戶端變化。它提供了一種簡潔的方式來切換和封裝演算法,提高了程式碼的可讀性和可維護性。

案例場景:

在商場收銀系統中,可以正常收費,即按照單價*數量得出價格,遇到活動時可以打折收費和返利收費,從而計算價格。

Strategy

/// <summary>
    /// 抽象策略角色
    /// </summary>
    public abstract class PayBase
    {
        /// <summary>
        /// 結算計算方式
        /// </summary>
        /// <param name="money"></param>
        /// <returns></returns>
        public abstract double Calc(double money);
    }

Concrete Strategy

/// <summary>
    /// 正常收費
    /// </summary>
    public class NormalPay : PayBase
    {
        public override double Calc(double money)
        {
            return money;
        }
    }
/// <summary>
    /// 折扣收費
    /// </summary>
    public class RebatePay : PayBase
    {
        private double rebate = 1;

        public RebatePay(double rebate)
        {
            if(rebate < 0 || rebate > 1)
            {
                throw new ArgumentException("折扣在0-1之間");
            }

            this.rebate = rebate;
        }

        public override double Calc(double money)
        {
            return money * rebate;
        }
    }
/// <summary>
    /// 滿減收費
    /// </summary>
    public class SubtractPay : PayBase
    {
        public int level = 0;
        public int subMoney = 0;
        public SubtractPay(int level, int subMoney)
        {
            this.level = level;
            this.subMoney = subMoney;
        }

        public override double Calc(double money)
        {
            int v = (int)(money / level);
            return money - v * subMoney;
        }
    }

Context

/// <summary>
    /// 打折
    /// </summary>
    public class PayContext
    {
        private PayBase Pay = new NormalPay();

        public void SetPayMode(PayBase pay)
        {
            Pay = pay;
        }

        public double GetResult(double money)
        {
            return Pay.Calc(money);
        }
    }

呼叫

internal class Client
    {
        public void Start()
        {
            double sumMoney = 10 * 18.5;//數量*單價=總價
            double realMoney = 0;//最終支付費用

            Console.WriteLine($"應付:{sumMoney}");

            PayContext context = new PayContext();

            //正常收費
            realMoney = context.GetResult(sumMoney);
            Console.WriteLine($"正常收費:{realMoney}");

            //扣扣收費
            context.SetPayMode(new RebatePay(0.85));
            realMoney = context.GetResult(sumMoney);
            Console.WriteLine($"扣扣收費:{realMoney}");

            //滿減收費
            context.SetPayMode(new SubtractPay(100,5));
            realMoney = context.GetResult(sumMoney);
            Console.WriteLine($"減收費:{realMoney}");

        }
    }
static void Main(string[] args)
        {
            new Client().Start();   

            Console.ReadKey();
        }

相關文章