策略模式(Strategy):
定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication1 7 { 8 enum Coupon 9 { 10 NoCoupon, 11 Discount, 12 ReturnM 13 } 14 15 #region 16 17 abstract class CashSuper 18 { 19 public abstract double acceptCash(double money); 20 } 21 22 class CashNormal: CashSuper 23 { 24 public override double acceptCash(double money) 25 { 26 return money; 27 } 28 } 29 30 class CashRebate: CashSuper 31 { 32 private double rebate = 1d; 33 34 public CashRebate(double rebate) 35 { 36 this.rebate = rebate; 37 } 38 39 public override double acceptCash(double money) 40 { 41 return money * rebate; 42 } 43 } 44 45 class CashReturn : CashSuper 46 { 47 private double moneyCondition = 0.0; 48 private double moneyReturn = 0.0d; 49 50 public CashReturn(double moneyCondition, double moneyReturn) 51 { 52 this.moneyCondition = moneyCondition; 53 this.moneyReturn = moneyReturn; 54 } 55 56 public override double acceptCash(double money) 57 { 58 double result = money; 59 60 if(money > moneyCondition) 61 { 62 result = money - Math.Floor(money/moneyCondition) * moneyReturn; 63 } 64 65 return result; 66 } 67 } 68 69 #endregion 70 71 #region Strategy Context 72 73 // Factory Pattern and Strategy Pattern 74 class CashContext 75 { 76 private CashSuper cs = null; 77 78 public CashContext(Coupon cp) 79 { 80 switch(cp) 81 { 82 case Coupon.NoCoupon: 83 cs = new CashNormal(); 84 break; 85 case Coupon.Discount: 86 cs = new CashRebate(0.8); 87 break; 88 case Coupon.ReturnM: 89 cs = new CashReturn(300, 100); 90 break; 91 } 92 } 93 94 public double GetResult(double money) 95 { 96 return this.cs.acceptCash(money); 97 } 98 } 99 100 #endregion 101 102 class Program 103 { 104 static void Main(string[] args) 105 { 106 CashContext cs = new CashContext(Coupon.Discount); 107 double d1 = cs.GetResult(500); 108 109 cs = new CashContext(Coupon.ReturnM); 110 double d2 = cs.GetResult(700); 111 112 Console.ReadLine(); 113 } 114 } 115 }
以上实例中,在策略模式中使用了工厂模式,可见工厂模式并非只有建立一个工厂类的做法。
本示例中, 也可以用简单工厂模式去实现,不过它需要客户端认识两个类去完成;而使用策略模式,只需要认识一个Context类就可以了,耦合降低了。
策略模式封装了变化。模式策略就是用来封装算法的。但是在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的规则,就可以考虑使用策略模式处理这种变化的可能性。
在基本的策略模式中,选择所有具体实现的职责由客户端对象承担,并转给策略模式的Context对象,这本身并没有解除客户端选择判断的压力,而策略模式与简单工厂模式结合之后,选择具体的职责可以由Context来承担,这最大化的减轻了客户端的职责。