策略模式是一种定义了一系列算法的方法,这些算法完成的都是类似的工作,只是实现不同,可以以相同的方法调用所有的算法,减少了各种算法类与使用算法类之间的耦合。一般只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性,下面用策略模式结合简单工厂模式实现商场的不同打折算法:
1 多种打折算法的实现
/// <summary> /// 打折算法接口 /// </summary> public abstract class CashSuperStrategy { public abstract double CashCaulate(double money); } /// <summary> /// 不打折算法 /// </summary> public class CashNormalStrategy : CashSuperStrategy { public override double CashCaulate(double money) { return money; } } /// <summary> /// 打折算法 /// </summary> public class CashRebateStrategy : CashSuperStrategy { private double rebate = 1d; public CashRebateStrategy(double cashRebate) { this.rebate = cashRebate; } public override double CashCaulate(double money) { return money * rebate; } } /// <summary> /// 满额返现算法 /// </summary> public class CashReturnStrategy : CashSuperStrategy { private double moneyConditon = 0d; private double moneyReturn = 0d; public CashReturnStrategy(double moneyConditon, double moneyReturn) { this.moneyConditon = moneyConditon; this.moneyReturn = moneyReturn; } public override double CashCaulate(double money) { double result = money; if (money>=moneyConditon) { result = money - Math.Floor(money / moneyConditon) * moneyReturn; } return result; } }
2 引入Context类,根据客户端不同参数使用不同的算法
/// <summary> /// 结合策略模式和简单工厂模式 /// </summary> public class Context { CashSuperStrategy strategy; /// <summary> /// 此处结合简单工厂模式,将实例化的职责由客户端转移到了Context类中 /// 减轻了客户端的职责和客户端与算法类的耦合度 /// </summary> /// <param name="discountType"></param> public Context(string discountType) { switch (discountType) { case "正常收费": strategy = new CashNormalStrategy(); break; case "打7折": strategy = new CashRebateStrategy(0.7); break; case "满300返100": strategy=new CashReturnStrategy(300,100); break; } } public double GetResult(double money) { return strategy.CashCaulate(money); } }
3 客户端使用Context类,间接使用不同的算法
/// <summary> /// 这种实现方法对于客户端,只需要认识Context类,完全不需要了解任何算法类,甚至不需要了解算法类的接口 /// </summary> /// <param name="args"></param> static void Main(string[] args) { Context context1 = new Context("正常收费"); double result1 = context1.GetResult(100); Console.WriteLine(result1); Console.ReadLine(); Context context2 = new Context("打7折"); double result2 = context2.GetResult(100); Console.WriteLine(result2); Console.ReadLine(); Context context3 = new Context("满300返100"); double result3 = context3.GetResult(300); Console.WriteLine(result3); Console.ReadLine(); }
执行代码,运行结果为:
100
70
200
当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行。而将这些行为封装在一个个独立的Strategy类中,可以在使用这些行为的类中消除条件语句。至于简单工厂中的条件语句则可以结合反射和配置文件解决。