定义了算法的家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的用户。【DP定义】
从概念上来说,所有的算法完成的工作都是相同的,只是实现不同,策略模式可以以相同的方式调用不同的算法,减少了各种算
法类与使用算法类之间的耦合。
应用场合:不同的时间或者不同的情况下使用不同的业务规则时可以考虑使用策略模式。
实例:商场收银软件
根据购买物品的单价和数量以及促销规则,计算客户所买物品的总价。
为了方便起见,促销规则假定设置为:正常收费,打折收费,返利收费
分别用简单工厂模式和策略模式来实现。具体见代码分析
/// <summary>
/// 公共父类:现金收取抽象类
/// 整个系统的目的就是为了最后得到客户消费的总额,所以抽象父类中
/// 实现获取物品的价格
/// </summary>
public abstract class CashSuper
{
/// <summary>
/// 返回物品的价格
/// </summary>
/// <param name="money">物品原价</param>
/// <returns></returns>
public abstract double GetMoney(double money);
}
/// <summary>
/// 正常收费子类
/// </summary>
public class CashNormal:CashSuper
{
/// <summary>
/// 返回原价
/// </summary>
/// <param name="money"></param>
/// <returns></returns>
public override double GetMoney(double money)
{
return money;
}
}
/// <summary>
/// 打折收费子类
/// </summary>
public class CashRebate:CashSuper
{
/// <summary>
/// 打折率
/// </summary>
private double _moneyRebate = 1d;
public CashRebate(double moneyRebate)
{
this._moneyRebate = moneyRebate;
}
/// <summary>
/// 打折收费
/// </summary>
/// <param name="money"></param>
/// <returns></returns>
public override double GetMoney(double money)
{
double retMoney = 0;
if (this._moneyRebate <= 0)
{
retMoney = money;
throw new Exception("呵呵,天上不会掉馅饼的哦!");
}
else
{
retMoney =money *_moneyRebate ;
}
return retMoney;
}
}
/// <summary>
/// 返利收费子类
/// </summary>
public 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(double moneyCondition, double moneyReturn)
{
this._moneyCondition = moneyCondition;
this._moneyReturn = moneyReturn;
}
public override double GetMoney(double money)
{
double retMoney = money;
if (money >= _moneyCondition)
{
retMoney = money - Math.Floor(money / _moneyCondition) * _moneyReturn;
}
return retMoney;
}
}
首先我们用简单工厂模式来实现
/// <summary>
/// 简单工厂类:现金收费类
/// </summary>
public class CashFactory
{
public static CashSuper CreateCashAccept(string type)
{
CashSuper cs = null;
switch (type)
{
case "正常收费":
cs = new CashNormal();
break;
case "打八折":
cs = new CashRebate(0.8);
break;
case "满300返100":
cs = new CashReturn(300, 100);
break;
}
return cs;
}
}
客户端实现代码:
//总计
double totalPrice = 0.0d;
private void btnSure_Click(object sender, EventArgs e)
{
try
{
//简单工厂模式实现
StrategyPattern.CashSuper cs = CashFactory.CreateCashAccept(this.cmbDisCount.SelectedItem.ToString());
double total = 0.0d;
total = cs.GetMoney(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtNum.Text);
totalPrice = totalPrice + total;
listDetailes.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text + " "
+ cmbDisCount.SelectedItem.ToString() + " 合计:" + total.ToString());
this.lblTotal.Text = totalPrice.ToString() + " 元";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
简单工厂和策略模式结合实现:
/// <summary>
/// 实例化具体的策略,根据不同的策略对象,调用起算法的方法
/// </summary>
public class CashContext
{
private CashSuper _cs;
//public CashContext(CashSuper cs)
//{
// this._cs = cs;
//}
///// <summary>
///// 更加收费策略的不同,获得计算结果
///// </summary>
///// <param name="money"></param>
///// <returns></returns>
//public double GetMoney(double money)
//{
// return _cs.GetMoney(money);
//}
//简单工厂与策略模式的结合
/// <summary>
/// 在实例化公共策略类时根据不同的收费方式决定了使用哪种策略来计算
/// </summary>
/// <param name="type"></param>
public CashContext(string type)
{
switch (type)
{
case "正常收费":
CashNormal cn = new CashNormal();
_cs = cn;
break;
case "打八折":
CashRebate cr = new CashRebate(0.8);
_cs = cr;
break;
case "满300返100":
CashReturn cre = new CashReturn(300, 100);
_cs = cre;
break;
}
}
public double GetMoey(double money)
{
return _cs.GetMoney(money);
}
}
客户端实现代码:
//总计
double totalPrice = 0.0d;
private void btnSure_Click(object sender, EventArgs e)
{
try
{
//简单工厂模式实现
//StrategyPattern.CashSuper cs = CashFactory.CreateCashAccept(this.cmbDisCount.SelectedItem.ToString());
//double total = 0.0d;
//total = cs.GetMoney(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtNum.Text);
//totalPrice = totalPrice + total;
//listDetailes.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text + " "
// + cmbDisCount.SelectedItem.ToString() + " 合计:" + total.ToString());
//this.lblTotal.Text = totalPrice.ToString() + " 元";
//简单工厂和策略的结合
//优点:在使用简单工厂模式时在客户端我们需要实例化两个类,而策略模式与简单工厂的结合,
//客户端只需要实例化一个类就可以了。耦合度更低
CashContext cc = new CashContext(this.cmbDisCount.SelectedItem.ToString());
double total = 0.0d;
total = cc.GetMoey(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtNum.Text);
totalPrice = totalPrice + total;
listDetailes.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text + " "
+ cmbDisCount.SelectedItem.ToString() + " 合计:" + total.ToString());
this.lblTotal.Text = totalPrice.ToString() + " 元";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
好了,策略模式就介绍到这儿,代码中有好多部分还可以优化,有兴趣的同仁们不妨可以改该。
如有需要源代码的朋友们,可以给我留下您的邮箱,我会及时发送给您。