大话设计模式-策略模式
策略模式
它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。
优点
策略模式是一种定义了一系列算法的方法,从个概念上看,所有这些算法完成的都是相同的工作。只是实现不同。他可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
策略模式优化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
不足
策略模式就是用来封装算法的,选择具体实现的职责由客户端对象承担,并转给策略模式的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(); } }