软件设计 2017-01-04
在上一篇博文结尾中,提到了存在的问题,那么我们通过策略模式与简单工厂结合的方式来解决上篇结尾中提到的问题。
方法很简单,我们将CashContext简单的改造一下即可
1 class CashContext
2 {
3 CashSuper cs = null;
4 public CashContext(string type)
5 {
6 switch (type)
7 {
8 case "正常收费":
9 cs = new CashNormal();
10 break;
11 case "满300返100":
12 cs = new CashReturn("300", "100");
13 break;
14 case "打8折":
15 cs = new CashRebate("0.8");
16 break;
17 }
18 }
19 public double GetResult(double money)
20 {
21 return cs.acceptCash(money);
22 }
23 } 哈哈,是不是很像一个工厂?
那么,客户端调用起来就非常非常简单了。
double total = 0.0d;
/// <summary>
/// 点击确定按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OK_Click(object sender, EventArgs e)
{
CashContext cc = new CashContext(cobEvent.SelectedItem.ToString());
double totalPrices = 0d;
totalPrices = cc.GetResult(Convert.ToDouble(UnitPrice.Text) * Convert.ToDouble(Count.Text));
total = total + totalPrices;
listTotal.Items.Add($"单价:{UnitPrice.Text} 数量:{Count.Text} 优惠方式:{cobEvent.SelectedItem} 合计:{totalPrices.ToString()}");
} 嗯,是不是很简洁明了?
很多刚开始接触设计模式的小伙伴有这样一个感觉:策略模式和简单工厂模式没啥区别啊,感觉都差不多啊。
嗯,一开始我也是这么认为的。但,小伙伴们,睁大眼睛请看一下。
若 简单工厂 模式,客户端是这样的:
CashSuper csuper=CashFactory.createCashAccept(cobEvent.SelectedItem.ToString()); ......=csuper.GetResult(....);
若 策略模式 ,客户端是这样的:
CashContext csuper=new CashContext(cobEvent.SelectedItem.ToString()); ......=csuper.GetResult(....);
看出啥区别来了吗? 小伙伴们不禁要说了,这有啥区别,在我看来,这点区别没啥用啊。
好,下面我就点出区别的本质。
简单工厂:客户端需要认识两个类,CashSuper和CashFactory。
策略模式:客户端只需要认识一个类,CashContext就可以了。
综上,策略模式耦合更加降低。这使得具体的收费算法彻底的与客户端分离,连算法的父类 CashSuper都不用让客户端认识了。
OK,策略模式和简单工厂的结合讲完了,他俩的区别也给大家说了,那么,很多很多的小伙伴不禁要说了:即便是用了简单工厂+策略模式结合,都避免不了一个问题,那就是 如果商场需要增加一种新的算法,就必须改CashContext中的switch代码,这总让人不爽啊。
任何需求的变更都是需要成本的,但是成本的高低还是有差异的。高手和菜鸟的区别就是,高手可以花同样的代价获得最大的收益,或者说,做同样的事,花最小的代价。面对同样的需求,当然是改动越小越好。
面对上述小伙伴们提出的问题,我们有一个很好的解决办法,那就是反射技术,在此我们先不展开将了,我会在后面的博文中给大家讲解。
好了,今天就到这吧,下一篇,会讲 装饰模式
本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持。