16_策略模式

策略模式是一种行为型设计模式,它定义了一系列的算法,并将每个算法封装到独立的类中,使它们可以互相替换。策略模式使得算法可以独立于客户端而变化,客户端可以根据需要选择不同的算法。

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

  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();
        }

 

posted @ 2024-03-14 09:17  野码  阅读(11)  评论(0编辑  收藏  举报