前言
最近开始和春哥,张铎 ,银平讨论设计模式,成立了一个小菜变大鸟的小组,每天讨论一个模式,并且把这个模式搞懂,每学一个新的模式,再回顾一下之前学的模式。这两天学了简单工厂模式和策略模式,发现两个模式有很多相同之处,下面用商场促销的例子来对两个模式总结一下。
简单工厂模式
1.首先建立一个抽象类,用以子类继承,定义了抽象方法 acceptCash() 方法传入参数 money
abstract class CashSuper
{
public abstract double acceptCash(double money);
}
2.这里定义了三个子类,分别处理 正常收费 , 打折 , 满300返100 三种收费方法。
class CashNormal : CashSuper
{
public override double acceptCash(double money)
{
return money;
}
}
class CashRebate : CashSuper
{
private double rebate = 1d;
public CashRebate(string Rebate)
{
rebate = Convert.ToDouble(Rebate);
}
public override double acceptCash(double Money)
{
return Money * rebate;
}
}
class CashReturn : CashSuper
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
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;
}
}
大话模式的第一章的简单工厂模式是用父类实现多态,这里体现的是用抽象类实现多态。
3.下面是工厂类
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 "打七折":
cs = new CashRebate("0.7");
break;
case "满300返100":
cs = new CashReturn("300","100");
break ;
}
return cs;
}
4.然后是客户端的代码
public Form1()
{
InitializeComponent();
}
double total = 0.0d;
private void button1_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));
total = total + totalPrices;
lbxList.Items.Add("单价:" + txtPrice.Text +"数量:" + txtNum.Text + cbxType.SelectedItem + "合计:" + totalPrices.ToString());
label4.Text = total.ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
cbxType.Items.AddRange(new object[] { "正常收费", "打八折", "满300返100"});
cbxType.SelectedIndex = 0;
}
}
首先创建 CashSuper 对象,调用工厂类的 createCashAccept()方法,根据传入的字符串(正常收费,打八折)返回相应的 CashSuper 对象,然后执行刚才复写的 acceptCash()方法,传入参数 money 进行计算。
优点:通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
策略模式
策略模式的概念:策略模式定义了算法家族,分别封装起来,让他们之间可以相互替换,策略模式让算法的变化不会影响到使用算法的客户。
同样的例子使用策略模式更改一下,CashSuper和三种处理方法不用更改,只需在简单工厂基础上添加 CashContext 类:
class CashContext
{
private CashSuper cs;
public CashContext(CashSuper csuper)
{
this.cs = csuper;
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
客户端代码如下,将相应的策略对象作为参数传入 CashContext 对象中:
private void button1_Click(object sender, EventArgs e)
{
CashContext cc = null ;
switch(cbxType .SelectedItem.ToString())
{
case "正常收费":
cc = new CashContext (new CashNormal());
break ;
case "打八折":
cc = new CashContext (new CashRebate("0.8"));
break ;
case "满300返100":
cc = new CashContext (new CashReturn("300","100"));
break ;
}
double totalPrice = 0d;
totalPrice = cc.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
比较简单工厂的方法知道,简单工厂需要客户端认识两个类 CashSuper 和 CashFactory ,而策略模式客户端只需要认识 CashContext 类就可以了,使得具体的收费算法彻底与客户端分离,耦合度更加降低。
策略与简单工厂结合
改造后的CashContext:将实例化具体策略的过程由客户端转移到Context类种。
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 "打八折":
CashRebate cr2 = new CashRebate("0.8");
cs = cr2;
break;
}
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
}
客户端端代码如下:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double total = 0.0d;
private void button1_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));
total = total + totalPrices;
lbxList.Items.Add("单价:" + txtPrice.Text +"数量:" + txtNum.Text + cbxType.SelectedItem + "合计:" + totalPrices.ToString());
label4.Text = total.ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
cbxType.Items.AddRange(new object[] { "正常收费", "打八折", "满300返100"});
cbxType.SelectedIndex = 0;
}
}
总结
比较简单工厂的方法知道,简单工厂需要客户端认识两个类 CashSuper 和 CashFactory ,而策略模式客户端只需要认识 CashContext 类就可以了,使得具体的收费算法彻底与客户端分离,耦合度更加降低。
刚开始学,感觉学的还不够深入,如有错误,还望指教。