设计模式(1)(2):简单工厂模式和策略模式
来源:互联网 发布:吃肉 知乎 编辑:程序博客网 时间:2024/06/11 01:58
在这里以书中 商场促销 为例分析一下 简单工厂模式,所谓设计模式,我认为最主要的就是竟可能实现代码的封装,达到代码模块之间低耦合的目的,这就用到了继承和多态,看看代码实现。
首先,建立一个抽象类,用于子类继承,定义了抽象方法 acceptCash() 方法传入参数 money ,实现相应算法
<span style="font-size:14px;">public abstract class CashSuper{ public abstract double acceptCash(double money);}</span>
这里定义了三个子类,分别处理 正常收费 , 打折 , 满300返100 三种收费方法,复写 acceptCash()方法,这就是多态的体现吧
<span style="font-size:14px;"> /// <summary> /// 正常收费子类,输入 money,无变化直接返回 money /// </summary> public class CashNormal : CashSuper { public override double acceptCash(double money) { return money; } }</span>
</pre><p></p><pre name="code" class="csharp"><span style="font-size:14px;"> /// <summary> /// 打折收费子类,<span style="font-family: Arial, Helvetica, sans-serif;">CashRebate() 构造函数传入折扣率,如八折为0.8</span> /// </summary> public class CashRebate : CashSuper { private double moneyRebate = 1d; public CashRebate(string moneyRebate) { this.moneyRebate = double.Parse(moneyRebate); } public override double acceptCash(double money) { return money * moneyRebate; } }</span>
<span style="font-size:14px;"> /// <summary> /// 返现收费子类,<span style="font-family: Arial, Helvetica, sans-serif;">CashReturn() 两个参数,满300和返100</span> /// </summary> public 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; } }</span>
下面就是工厂类了
<span style="font-size:14px;"> /// <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 "打七折": cs = new CashRebate("0.7"); break; case "满300返100": cs = new CashReturn("300","100"); break ; } return cs; } }</span>简单工厂职责就是根据传入的参数判断返回的 CashSuper 对象,进而由该对象进行相应的操作,看看客户端代码就明白了
<span style="font-size:14px;"> private void button_收费_Click(object sender, EventArgs e) { CashSuper csuper = CashFactory.createCashAccept(cbxType.SelectedItem.ToString()); double totalPrice = 0d; totalPrice = csuper.acceptCash(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text)); }</span>
首先创建 CashSuper 对象,调用工厂类的 createCashAccept()方法,根据传入的字符串(正常收费,打八折……)返回相应的 CashSuper 对象,然后执行刚才复写的 acceptCash()方法,传入参数 money 进行计算。
引用一下百度的:
就像本例中一样,简单工厂模式虽然能解决功能问题,实现了代码的封装较低了模块间耦合性,但是这个设计模式只解决了对象的创建问题,而且由于工厂本身包括了所有的收费方式,商场是可能经常性的更改打折额度和返利额度的,每次维护和扩展收费方式都要改动工厂,以至于代码需要重新编译部署,面对算法的时常改动 策略模式 或许是一种好的方法。
策略模式定义了算法家族,分别封装起来,让他们之间可以相互替换,策略模式让算法的变化不会影响到使用算法的客户。
商场收银时候如何促销,用打折还是返利,其实都是一些算法,用工厂来实现算法本身没有错。但算法本身只是一种策略,最重要的是这些算法都是针对同一问题的不同解决方案,他们之间随时可以相互更换,这就是变化点,而封装变化点是面向对象的一种很重要的思维方式。
同样的例子,使用策略模式进行修改:
CashSuper和三种处理方法不用更改,只需在简单工厂基础上添加 CashContext 类
<span style="font-size:14px;"> class CashContext { private CashSuper cs; public CashContext(CashSuper csuper) { this.cs = csuper; } public double GetResult(double money) { return cs.acceptCash(money); } }</span>客户端代码如下,将相应的策略对象作为参数传入 CashContext 对象中
<span style="font-size:14px;"> 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)); }</span>通过对 Context 的 GetResult() 方法的调用,可以得到收取费用的结果,让具体的算法与客户端进行了分离。现在判断是在客户端实现的,并没有减轻客户端需要选择判断的压力,再次改进,仿照简单工厂方法将客户端判断移走,修改 CashContext 类
<span style="font-size:14px;"> class CashContext { private CashSuper cs; public CashContext(string type) { switch (type) { case "正常收费": cs = new CashNormal(); break; case "打八折": cs = new CashRebate("0.8"); break; case "满300返100": cs = new CashReturn("300", "100"); break; } } public double GetResult(double money) { return cs.acceptCash(money); } }</span>客户端代码如下
<span style="font-size:14px;">CashContext csuper = new CashContext(cbxType.SelectedItem.ToString()); double totalPrice = 0d; totalPrice = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));</span>比较简单工厂的方法知道,简单工厂需要客户端认识两个类 CashSuper 和 CashFactory ,而策略模式客户端只需要认识 CashContext 类就可以了,使得具体的收费算法彻底与客户端分离,耦合度更加降低。
策略模式就是用来封装算法的,只要在分析中听到需要在不同时间响应不同的业务规则,就可以考虑使用策略模式处理这种变化。
策略模式是一种定义了一系列算法的方法,从概念上看,所有的方法都完成了相同的工作,只是实现方法不同,他们可以以相同的方式调用所有的算法,减少了各种算法类与算法实用类之间的耦合。另外策略模式还有简化了单元测试的优点,修改任何一个算法都不会影响其他。
初次学习设计模式,心得写下来和大家分享,如有错误还望大家不吝赐教。
- 设计模式(1)(2):简单工厂模式和策略模式
- 设计模式(一):策略模式+简单工厂模式
- 设计模式--简单工厂模式 策略模式
- 设计模式之简单工厂模式和策略模式(计算器实现)
- 设计模式学习之简单工厂模式和策略模式
- 设计模式之简单工厂模式和策略模式总结
- 设计模式-简单工厂模式和策略模式
- java设计模式之策略模式和简单工厂模式
- 设计模式(二)简单工厂与策略模式
- 设计模式解读 之策略模式(参照策略模式与简单工厂模式的对比)
- 设计模式实现(二)---策略模式、策略模式与简单工厂模式结合使用
- 设计模式解读 之策略模式(参照策略模式与简单工厂模式的对比)
- Java设计模式-工厂模式(1)简单工厂模式
- 设计模式之简单工厂模式,工厂模式,策略模式
- 大话设计模式1 简单工厂模式 策略模式
- 设计模式(2)-简单工厂模式
- 设计模式(2)简单工厂模式
- 设计模式(2)-简单工厂模式
- 一大波 开源项目 优秀节目展示
- 微信分享 不借助新版sdk 的分享方法
- Spring系列(5)---IOC技术.
- StringBuffer和StringBuilder
- 安卓动画系列之二,补间动画(Tween Animation)以及动画结合LayoutAnimation的好处
- 设计模式(1)(2):简单工厂模式和策略模式
- 国内App推广终极37个方法
- mongodb_修改器($inc/$set/$unset/$push/$pop/upsert/$rename)-转载补充
- 从上往下打印二叉树
- hdu 3507 Print Article(dp斜率优化)
- Spring系列(6)---总结(1)
- ubuntu 避免’sudo echo x >’ 时’Permission denied’
- centos6下无法使用lsof命令"-bash: lsof: command not found"
- C语言及程序设计初步例程-11 算术运算符与算术表达式