设计模式-策略模式结合简单工厂
前言:
策略模式可以定义一系列的算法,并且根据需求选择算法。算法之间还可以相互替换,不影响客户端的使用。
需求:
还是以商场的收银系统为例,这次添加一个需求。在上一个需求上加一个,打5折和打7折的需求。
类图:
实现:
抽象策略类(没有具体的实现策略,而是把具体策略的共同方法抽象到里面)
/// <summary>
/// 现金收费的抽象类,父类。
/// </summary>
abstract class CashSuper
{
/// <summary>
/// 现金收费的抽象方法
/// </summary>
/// <param name="money">原价</param>
/// <returns>当前价格</returns>
public abstract double acceptCash(double money);
}//end CashSuper
正常收费策略(继承抽象策略类)
/// <summary>
/// 正常收费子类
/// </summary>
class CashNormal : CashSuper
{
/// <summary>
/// 重写父类的收费方法
/// </summary>
/// <param name="money">原价</param>
/// <returns>当前价格</returns>
public override double acceptCash(double money)
{
return money;//原价返回
}//end acceptCash
}//end CashNormal
打折策略(继承抽象策略类)
/// <summary>
/// 打折收费子类
/// </summary>
class CashRedbate : CashSuper
{
private double moneyRebate = 1d;//具体打几折
/// <summary>
/// 获取具体打几折
/// </summary>
/// <param name="moneyRebate">具体打几折</param>
public CashRedbate(string moneyRebate)
{
this.moneyRebate = double.Parse(moneyRebate);
}//end CashRedbate
/// <summary>
///打折的方法
/// </summary>
/// <param name="money">原价</param>
/// <returns>打折之后的价格</returns>
public override double acceptCash(double money)
{
//原价*具体打折数=打折之后的价格
return money * moneyRebate;
}//end aceptCash
}//end CashRedbate
返利策略(继承抽象策略类)
/// <summary>
/// 返利收费子类
/// </summary>
class CashReturn : CashSuper
{
private double moneyCondition = 0.0d;//返利条件
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);//反多少
}//end CashRetur
/// <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;
}//end if
return result;//返回价格
}//end AcceptCash
}//end CashReturn
客户端(在客户端用switch选择具体的策略,把选好的具体策略传入CashFactoury里面。然后根据传进去的策略进行具体的计算。)
double total = 0.0d;
private void butok_Click(object sender, EventArgs e)
{
CashContext cc = null;//实例化策略模式
//根据条件选择策略
switch (cbxType.Selecteditem.Tostring())
{
case "正常收费":
cc = new CashNormal();
break;
case "满300返100":
cc = new CashReturn("300", "100");
break;
case "打8折":
cc = new CashRedbate("0.8");
break;
case "打5折":
cc = new CashRedbate("0.5");
break;
case "打7折":
cc = new CashRedbate("0.7");
break;
}//end switch
double totalprices = 0d;//金额
totalprices = cc.GetResult(Convert.ToDouble(txtNumber1.Text )
*Convert.ToDouble(txtNumber2.Text));
//累加
total = total + totalprices;
listBox1.Items.Add("单价:" + txtNumber1.Text + "数量:" + txtNumber2.Text + "\t" +
combType.SelectedItem + "合计:" + totalprices.ToString());
lblmony.Text = total.ToString();
}
}//end createCashAccept
反思:
在第一个简单工厂模式我们就把客户端的判断部分移动到了后端,但是在策略模式这里我们又把判断部分移到了客户端。让客户端来选择具体使用哪个策略。
解决方案:
我们可以把策略模式和简单工厂模式结合使用,这样即解决了算法可以灵活替换还把选择部分又移动到了后端。
策略模式+简单工厂模式:(只需要修改原来的CashFactory类和客户端代码)
CashFactory类
class CashFactory
{
CashSuper cs = null;//实例化父类
/// <summary>
/// 根据需要实例化对象
/// </summary>
/// <param name="type">需要实例化的对象名</param>
/// <returns>返回实例化之后的对象</returns>
public CashFactory(string type)
{
//判断选择了哪种优惠方案
switch (type)
{
case "正常收费":
cs = new CashNormal();
break;
case "满300返100":
cs = new CashReturn("300", "100");
break;
case "打8折":
cs = new CashRedbate("0.8");
break;
case "打5折":
cs = new CashRedbate("0.5");
break;
case "打7折":
cs = new CashRedbate("0.7");
break;
}//end switch
}//end createCashAccept
/// <summary>
/// 根据具体实例化对象,调用方法。
/// </summary>
/// <param name="money">原价</param>
/// <returns>当前价格</returns>
public double GetResult(double money)
{
return cs.acceptCash(money);
}//end GetResult
}//end class CashFactory
客户端(修改之后的)
double total = 0.0d;
private void butok_Click(object sender, EventArgs e)
{
//实例化策略工厂类
CashFactory cc = new CashFactory(combType.SelectedItem.ToString());
double totalprices = 0d;//金额
totalprices = cc.GetResult(Convert.ToDouble(txtNumber1.Text )
*Convert.ToDouble(txtNumber2.Text));
//累加
total = total + totalprices;
listBox1.Items.Add("单价:" + txtNumber1.Text + "数量:" + txtNumber2.Text + "\t" +
combType.SelectedItem + "合计:" + totalprices.ToString());
lblmony.Text = total.ToString();
}
结果:
欢迎访问csdn的博客:
https://blog.csdn.net/kangshihang1998?spm=1010.2135.3001.5343