02—策略模式
2016-02-25 21:08
204 查看
描述:是用来封装算法的,但在实践中,我们发现可以用来封装任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
简单说就是“策略模式封装了变化”。
实例:用一个超市促销活动收银的小例了来讲解一下,比如双11了,我们的超市要举行促销活动,活动类型分类:正常收费、满300返100、打8折三种。
那我们先分析一下,三种收费方式,每种的计算方式都不同,有很多种实现方式,我们先用简单工厂实现,然后在用策略模式实现,好下面我们先用简单工厂实现一下:
现金收费的基类
现金收费的子类 (放在一个文件中了CashSubAll.cs)
现金收费工厂类
客户端调用
下面是代码:点击下载
下面我们先来看看策略模式的简易代码:
上面的小例子看上去非常明了简单,和简单工厂有些像,那我们分析一下,超市活动的例子,CashSuper就是抽象策略,正常收费(CashNormal )、满300返100(CashReturn)、打8折(CashRebate)就是具体策略,只要加一个CashContext就可以了,下面我们就通过策略模式来实现超市现金收费的例子:
CashContext.cs
客户端调用
看到这样的客户端调用是不是欲哭无泪,又回到最古老的方式,在客户端判断写了好多代码,其实在这里我们还可以结合一下简单工厂模式:
CashContext.cs
客户端调用
好了,完成。代码:点击下载
简单说就是“策略模式封装了变化”。
实例:用一个超市促销活动收银的小例了来讲解一下,比如双11了,我们的超市要举行促销活动,活动类型分类:正常收费、满300返100、打8折三种。
那我们先分析一下,三种收费方式,每种的计算方式都不同,有很多种实现方式,我们先用简单工厂实现,然后在用策略模式实现,好下面我们先用简单工厂实现一下:
现金收费的基类
/// <summary> /// 现金收费的抽象类 /// </summary> abstract class CashSuper { /// <summary> /// 现金收取超类的抽象方法,收取现金,参数为原价,返回为当前价 /// </summary> /// <param name="money"></param> /// <returns></returns> public abstract double acceptCash(double money); }
现金收费的子类 (放在一个文件中了CashSubAll.cs)
/// <summary> /// 正常收费的子类 /// </summary> class CashNormal : CashSuper { public override double acceptCash(double money) { //正当收费,原价返回 return money; } } /// <summary> /// 打折收费子类 /// </summary> class CashRebate : CashSuper { private double moneyRebate = 1; /// <summary> /// 通过构造方法为私有变量赋值 /// </summary> /// <param name="moneyRebate"></param> public CashRebate(string moneyRebate) { this.moneyRebate = double.Parse(moneyRebate); } public override double acceptCash(double money) { return money * moneyRebate; } } /// <summary> /// 返利收费子类 /// </summary> class CashReturn : CashSuper { private double moneyCondition = 0; private double moneyReturn = 0; /// <summary> /// 通过构造方法,为返利收费初始化必要参数,比如“满300返100”,则moneyCodition为300,moneyReturn为100 /// </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); } public override double acceptCash(double money) { double result = money; //判断是不是满足返利条件,如果足减去返利金额 if (money >= moneyCondition) { result = money - Math.Floor(money/moneyCondition)*moneyReturn; } return result; } }
现金收费工厂类
/// <summary> /// 现金收费工厂类 /// </summary> class CashFactory { public static CashSuper createCashAccept(string type) { CashSuper cs = null; switch (type) { case "正常收费": cs = new CashNormal(); break; case "满300返100": cs = new CashReturn("300", "100"); break; case "打8折": cs = new CashRebate("0.8"); break; } return cs; } }
客户端调用
//通过简单工厂创建实例 CashSuper cs = CashFactory.createCashAccept(cbxType.SelectedItem.ToString()); double totalPrices = double.Parse(txtPrice.Text)*double.Parse(txtNum.Text); //调用简单工厂的方法 double result = cs.acceptCash(totalPrices); lboxListResult.Items.Add("总金额为:" + totalPrices + ",参加的活动为:" + cbxType.SelectedItem + ",应收金额:" + result);
下面是代码:点击下载
下面我们先来看看策略模式的简易代码:
// 抽象算法类 public abstract class Strategy { //算法方法 public abstract void AlgoritymInterface(); } // 具体算法A public class ConcreteStrategyA : Strategy { //算法A实现 public override void AlgoritymInterface() { Console.WriteLine("算法A"); } } // 具体算法B public class ConcreteStrategyB : Strategy { //算法B实现 public override void AlgoritymInterface() { Console.WriteLine("算法B"); } } /// <summary> /// 上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对像的引用 /// </summary> public class Context { Strategy stg = null; public Context(Strategy stg) { this.stg = stg; } //上下文接口 public void ContextInterface() { stg.AlgoritymInterface(); } } class Program { /// <summary> /// 客户端实现 /// </summary> /// <param name="args"></param> static void Main(string[] args) { Context context = null; context = new Context(new ConcreteStrategyA()); context.ContextInterface(); context = new Context(new ConcreteStrategyB()); context.ContextInterface(); Console.Read(); } }
上面的小例子看上去非常明了简单,和简单工厂有些像,那我们分析一下,超市活动的例子,CashSuper就是抽象策略,正常收费(CashNormal )、满300返100(CashReturn)、打8折(CashRebate)就是具体策略,只要加一个CashContext就可以了,下面我们就通过策略模式来实现超市现金收费的例子:
CashContext.cs
/// <summary> /// 上下文 /// </summary> public class CashContext { private CashSuper cs = null; public CashContext(CashSuper cs) { this.cs = cs; } /// <summary> /// 调用具体策略 /// </summary> /// <param name="moeny"></param> /// <returns></returns> public double GetResult(double moeny) { return cs.acceptCash(moeny); } }
客户端调用
double totalPrices = double.Parse(txtPrice.Text) * double.Parse(txtNum.Text); CashContext cc = null; switch (cbxType.SelectedItem.ToString()) { case "正常收费": cc = new CashContext(new CashNormal()); break; case "满300返100": cc = new CashContext(new CashReturn("300", "100")); break; case "打8折": cc = new CashContext(new CashRebate("0.8")); break; } double result = cc.GetResult(totalPrices); lboxListResult.Items.Add("总金额为:" + totalPrices + ",参加的活动为:" + cbxType.SelectedItem + ",应收金额:" + result);
看到这样的客户端调用是不是欲哭无泪,又回到最古老的方式,在客户端判断写了好多代码,其实在这里我们还可以结合一下简单工厂模式:
CashContext.cs
/// <summary> /// 上下文 /// </summary> public class CashContext { private CashSuper cs = null; /// <summary> /// 结合简单工厂 /// </summary> /// <param name="type"></param> public CashContext(string type) { switch (type) { case "正常收费": cs = new CashNormal(); break; case "满300返100": cs = new CashReturn("300", "100"); break; case "打8折": cs = new CashRebate("0.8"); break; } } /// <summary> /// 调用具体策略 /// </summary> /// <param name="moeny"></param> /// <returns></returns> public double GetResult(double moeny) { return cs.acceptCash(moeny); } }
客户端调用
double totalPrices = double.Parse(txtPrice.Text) * double.Parse(txtNum.Text); //策略上下文 CashContext cc = new CashContext(cbxType.SelectedItem.ToString()); double result = cc.GetResult(totalPrices); lboxListResult.Items.Add("总金额为:" + totalPrices + ",参加的活动为:" + cbxType.SelectedItem + ",应收金额:" + result);
好了,完成。代码:点击下载
相关文章推荐
- 数据结构——二叉查找树
- 往文件中写入内容(代码示例)
- new与malloc的区别
- python logging 替代print 输出内容到控制台和重定向到文件
- 字符串的定义、替换、比较、截取
- 谷歌推荐的图片加载框架--Glide的简单介绍
- Java 常见面试题整理
- HDU1532 - Drainage Ditches(网络流)
- 我们编程吧 之 Linux 学习手册0.41
- 网络编程_UDP编程原理_发送类型_cs与bs区别JAVA187-188
- 【POJ 2750】 Potted Flower(线段树套dp)
- TWinControl.DefaultHandler里的CallWindowProc(FDefWndProc)还挺有深意的,TButton对WM_PAINT消息的处理就是靠它来处理的(以前不明白为什么总是要调用inherited,其实就是没有明白TWinControl.DefaultHandler的真正用处,而且还很有用)
- Log4j详解
- 【ADO】回头复习,总是会有新的收获
- 一个自动根据xcode中的objective-c代码生成类关系图的神器
- MVC视图展现模式之移动布局解析-续集
- android开发之路01
- 内存计算
- 欢迎使用CSDN-markdown编辑器
- QT离线安装包下载地址