策略模式--实现商场打折
前言:
上一篇博客中写明了简单工厂的引用,其实这篇博客和上一篇类似,是利用了策略加简单工厂的方法实现的。为了我们的重构可以运用上设计模式,本次运用了客户端的形式展现出来,具体请往下看:
策略模式:
顾名思义即是:我提供不同的策略然后你自己选择即可。
定义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
小提示:
面向对象编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
请看类图 |
其中CashContext和CashSuper是聚合的关系,因为关联关系在VS中显示不出来。
下面请揭晓真正的代码(Windows) |
First:父子关系类
/// <summary>
/// 现金收费抽象类
/// </summary>
abstract class CashSuper
{
public abstract double acceptCash(double money);
//现金收取超类的抽象方法,收取现金,参数为原价,返回为当前价
}
/// <summary>
/// 正常收费子类
/// </summary>
class CashNormal : CashSuper
{
public override double acceptCash(double money)
{
//正常收费,原价返回
return money;
}
}
/// <summary>
/// 打折收费子类
/// </summary>
class cashRebate : CashSuper
{
private double moneyRebate = 1d;
public cashRebate(string moneyRebate)
{
//打折收费,初始化时,必需要输入折扣率,如八折,就是0.8
this.moneyRebate = double.Parse(moneyRebate);
}
public override double acceptCash(double money)
{
return money * moneyRebate;
}
}
/// <summary>
/// 返利收费子类
/// </summary>
class CashReturn : CashSuper
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
//返利收费,初始化时必须要输入返利条件和返利值,比如满300反100,则moneyCondition为300,monneyRetrun为100
public CashReturn(string moneyCondition, string moneyReturn)
{
this.moneyCondition = double.Parse(moneyCondition);
this.moneyReturn = double.Parse(moneyReturn);
}
public override double acceptCash(double money)
{
double result = money;
//若大于返利条件,则需要减去返利值
if (money >= moneyCondition)
{
result = money - Math.Floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
Secend: 添加一个工厂:
/// <summary>
/// CashContext类
/// </summary>
class CashContext
{
CashSuper cs = null;
public CashContext(string type)
{
switch (type )
{
case "正常收费":
CashNormal cs0 = new CashNormal();
cs = cs0;
break;
case "满300反100":
CashReturn cr1 = new CashReturn("300", "100");
cs = cr1;
break;
case "打8折":
cashRebate cr2 = new cashRebate("0.8");
cs = cr2;
break;
}
}
//根据收费策略的不同,获得计算结果
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
添加一个自动加载
//设置自动加载:只要是下拉框
private void Form1_Load(object sender, EventArgs e)
{
cbxType.Items.AddRange(new object[] { "正常收费", "满300反100", "打8折"});
cbxType.SelectedIndex = 0;
}
在客户端确定按钮中:
//客户窗体程序
double total = 0.0d;// 用于总计
private void btnOk_Click(object sender, EventArgs e)
{
CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
double totalprices = 0d;
totalprices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
//通过对Context的GetResult方法的调用,可以得到收取费用的结果,让具体算法与客户进行了隔离
total = total + totalprices ; //将每个商品合计计入总计。
lbxList.Items.Add("单价:" + txtPrice.Text + "数量:" + txtNum.Text + "合计:" + totalprices.ToString ());
//通过多态,可以得到收取费用的结果。
lblResult.Text = total.ToString(); //lab标签上显示总数量
}
以下就是制作的代码界面,前面的计算器没有给出,这次补上:
小结:
本次打折如果想添加其他优惠情况,则直接添加一个新类继承接口即可,并在工厂里面添加一个 case做为选择并在下拉框中显示出来即可。
基本策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象,只是我用了一个工厂将客户端的选择放进了Context中,相当于用了分治算法将复杂问题给分开。