16_策略模式
策略模式是一种行为型设计模式,它定义了一系列的算法,并将每个算法封装到独立的类中,使它们可以互相替换。策略模式使得算法可以独立于客户端而变化,客户端可以根据需要选择不同的算法。
策略模式有三个主要角色:
-
环境类(Context):它持有一个策略对象的引用,并在需要的时候调用策略对象的方法。环境类可以根据需要动态地替换策略对象。
-
抽象策略类(Strategy):定义了策略的抽象接口,通常包含一个或多个策略方法。
-
具体策略类(Concrete Strategy):实现了抽象策略接口,提供具体的算法实现。
策略模式的工作原理如下:
-
环境类持有一个策略对象的引用,并在需要的时候调用策略对象的方法。
-
客户端根据需要选择具体的策略类,并将其传递给环境类。
-
环境类根据传入的策略对象,调用相应的策略方法。
策略模式的优点包括:
-
提供了一种简洁的方式来封装和切换算法,使得算法可以独立于客户端变化。
-
可以避免使用大量的条件判断语句,提高了代码的可读性和可维护性。
-
可以通过继承和接口的方式扩展新的策略类。
策略模式适用于以下场景:
-
当多个类只有在算法或行为上有不同的情况下,可以使用策略模式。
-
当需要在运行时动态地选择不同的算法时,可以使用策略模式。
总结而言,策略模式通过将算法封装到独立的策略类中,使得算法可以独立于客户端变化。它提供了一种简洁的方式来切换和封装算法,提高了代码的可读性和可维护性。
案例场景:
在商场收银系统中,可以正常收费,即按照单价*数量得出价格,遇到活动时可以打折收费和返利收费,从而计算价格。
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(); }