策略模式其实很想一个简单工厂模式的再封装,简单工厂模式,在工厂Factory中生产的是对象。而策略模式的上下文Context不仅创建了对象,而且直接调用了对象的计算方法,给我们返回的计算出的值。
工厂模式,客户端需要(开发人员)需要记住父类和工厂类两个对象,通过参数创建对象,而策略模式,只需要创建context类,传入参数,调用方法就可以实现计算,少了一个类型,可以使客户端更加简洁。
策略模式,它的本质就是用来封装算法,将本来由客户端承担的对象选择的职责,转到Context中,减少了客户端的压力。
使用策略模式,要注意,策略模式里面的算法都是完成的相同的工作,只是这些工作实现的算法不同而已。
下面是策略模式的具体实现算法,使用的例子是一个收银台打折促销的算法
1.CashSuper类,这是一个父类,提供了一个根据策略计算出促销结果的抽象方法

1 /// <summary> 2 /// 现金收费抽象类 3 /// </summary> 4 abstract class CashSuper 5 { 6 /// <summary> 7 /// 现金收取抽象方法 8 /// </summary> 9 /// <param name="money">原价</param> 10 /// <returns>当前价</returns> 11 public abstract double AcceptCash(double money); 12 }
2.CashProduct,这是一系列具体实现算法的子类,继承自CashSuper父类

/// <summary> /// 正常收费子类 /// </summary> internal class CashNormal : CashSuper { /// <summary> /// 正常收费 /// </summary> /// <param name="money">价格</param> /// <returns>原价</returns> public override double AcceptCash(double money) { return money; } } /// <summary> /// 打折消费子类 /// </summary> internal class CashRebate : CashSuper { /// <summary> /// 初始化折扣为满折 /// </summary> private double moneyRebate = 1d; public CashRebate(string moneyRebate) { //通过构造方法获取折扣 this.moneyRebate = double.Parse(moneyRebate); } /// <summary> /// 进行打折计算 /// </summary> /// <param name="money">价格</param> /// <returns>打折后价格</returns> public override double AcceptCash(double money) { return money * moneyRebate; } } /// <summary> /// 返利消费子类 /// </summary> internal class CashReturn : CashSuper { /// <summary> /// 返利条件,需要达到的要求 /// </summary> private double moneyCondition = 0.0d; /// <summary> /// 返利值,达到返利条件所返利的金额 /// </summary> private double moneyReturn = 0.0d; /// <summary> /// 构造方法 /// </summary> /// <param name="moneyCondition"></param> /// <param name="moneyReturn"></param> public CashReturn(string moneyCondition, string moneyReturn) { this.moneyCondition = double.Parse(moneyCondition); this.moneyReturn = double.Parse(moneyReturn); } /// <summary> /// 返利消费计算 /// </summary> /// <param name="money">原价</param> /// <returns>现价</returns> public override double AcceptCash(double money) { double result = money; if (money >= moneyCondition) { result = money - Math.Floor(money / moneyCondition) * moneyReturn; } return result; } }
3CashContext,这是策略模式中最重要的一个类,它的功能是根据策略参数运用构造方法创建子类对象,并且定义了一个方法,根据实际参数进行对象方法的运行,得到结果

1 /// <summary> 2 /// 上下文 3 /// </summary> 4 class CashContext 5 { 6 private CashSuper cashSuper = null; 7 8 /// <summary> 9 /// 构造方法,根据参数得到返利对象 10 /// </summary> 11 /// <param name="type">返利类型</param> 12 public CashContext(string type) 13 { 14 switch (type) 15 { 16 case "正常收费": 17 cashSuper=new CashNormal(); 18 break; 19 case "满300反100": 20 cashSuper=new CashRebate("0.8"); 21 break; 22 case "打8折": 23 cashSuper=new CashReturn("300","100"); 24 break; 25 } 26 } 27 28 /// <summary> 29 /// 返利计算方法,根据对象计算出具体结果 30 /// </summary> 31 /// <param name="money">原价</param> 32 /// <returns>现价</returns> 33 public double GetResult(double money) 34 { 35 return cashSuper.AcceptCash(money); 36 } 37 }
4.客户端代码,因为大部分任务都给CashContext去做了,所以客户端没啥可做的,就创建了一个CashContext类用于子类对象的创建,兵器调用CashContext的计算方法得到结果

1 private void btnResult_Click(object sender, EventArgs e) 2 { 3 //根据下拉框的具体返利类型得到对象 4 var cashContext=new CashContext(cbxType.SelectedItem.ToString()); 5 //根据价格和数量获得采取了策略后的总价 6 var totalPrice = cashContext.GetResult(Convert.ToInt32(txtPrice.Text)*Convert.ToInt32(txtNum.Text)); 7 //得到结果 8 lbResult.Text = totalPrice.ToString(CultureInfo.InvariantCulture); 9 }
以上内容部分参考程杰的《大话设计模式》一书