模式人生-从生活中的点点滴滴认识设计模式2-策略模式(Strategy Pattern)
从生活中的点点滴滴认识设计模式系列(二)
策略模式(Strategy Pattern)
“唉!我没那种命啦,轮也不会轮到我,爱情老是缺货,我争什么?”一大清早就手机响,把我春天的梦都吵没了。
“喂,谁啊,大清早的还要不要人睡觉啦?”
“师傅,是我啦,小刘!”
“是你呀,是不是看我给你发的装饰器模式代码有问题要问我啦?”
“才不是啊,我可没那么笨,你的资料一看就懂了,有你这位大虾指导,我的设计模式之路无比光明!今天找你是有其它事情啦!”
“别拍马屁了,有什么事情就快说吧!”
“嗯,是这样的,为了答谢师傅的耐心指导,准备今天约师傅看电影,不知师傅肯赏脸否?”
哇,这可是天上掉下来的美差啊,抑制住心中的喜悦,淡淡的说:“我得看看今天的行程,这样吧,一会我回电话给你吧!”
“哦,这样啊,那好吧,等你电话哦!”
挂断电话后,抑制不住心中的喜悦,在床上跳起裸体机械舞。
哈哈,这回终于轮到我啦!
地点:北京万达电影城-CBD店 时间:下午3点 电影:变形金刚2
“你还没到啊?我都等了快一个小时了,你再不来,变形金刚都要离开地球啦!”
唉,做男人得有耐心,做好男人得有恒心。
功夫不负有心人,终于在远方看到了那熟悉的身影。
“真是不好意思啊,让你久等了,咱们上去吧!”
来到万达售票大厅,这人可不是一般的多,变形金刚的魅力还真不小。
排了N久的队,终于买到了变形金刚的电影票,离开影还有差不多1个小时,没地坐,只能找个角落站着傻等了。
看到别人丢在一旁的宣传单,没事拿起来看看。
“5000元办理万达至尊卡,享受电影票5折优惠;1000元办理万达钻石卡,享受电影票6折优惠;600元办理万达金卡,享受电影票7折优惠;300元办理万达银卡,享受电影票8折优惠。每张会员卡一场电影只能购买最多4张打折票。”
看到这广告,让我想起了一个设计模式,策略模式。
一旁的小刘正被大屏幕中播放的哈里波特预告片所吸引,我把她从哈里波特的世界里拉出来,把宣传单拿给她。
“看看这个,你看出来了什么?”
“呃……我看出来了4种会员卡!”
无语……
“你再认真看看,这上面的东西就是我今天要给你讲的设计模式:策略模式。”
“你看,宣传单上面4种会员卡就代表了万达的4种销售策略,策略模式就是将算法与其宿主类分离,将所有算法单独封装起来,这些算法完成的工作都相同,只是实现不同而已。对于会员只要知道他拥有哪种会员卡,而对于销售人员只要把会员的会员卡、票价和购买张数输入系统便能算出会员需支付的金额,而他们对这中间的算法根本不需要了解。”
听我说完,小刘点了点头:“明白了,银行利率跟这个也是一个道理。在银行存款活期和定期的利率不一样,定期存储时间长短不同,利率也不一样。所以银行系统应该也采用了策略模式把存款利率的算法都封装了起来,根据用户选择的存款方式选择不同的利率算法。”
“嗯,你理解得非常正确,和昨天一样,一会我回到家会把相关资料发给你。好了,电影要开影了,咱俩赶快进去吧!”
策略模式UML图:
Context:对一个算法类进行引用。
IStrategy:算法接口。
StrategyA:算法A,如万达会员卡的金卡购票7折。
StrategyB:算法B。
策略模式代码:
IStrategy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace StrategyPatterns { /// <summary> /// 算法接口 /// </summary> public interface IStrategy { /// <summary> /// 计算方法 /// </summary> /// <param name="ticketAmount">购票数量</param> /// <param name="unitPrice">单价</param> /// <returns>总金额</returns> double Algorithm(int ticketAmount, double unitPrice); } }
AceCardStrategy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Configuration; namespace StrategyPatterns { /// <summary> /// 至尊卡算法 /// </summary> public class AceCardStrategy : IStrategy { /// <summary> /// 计算方法 /// </summary> /// <param name="ticketAmount">购票数量</param> /// <param name="unitPrice">单价</param> /// <returns>总金额</returns> public double Algorithm(int ticketAmount, double unitPrice) { //购票限定数量 int limitNum = int.Parse(ConfigurationManager.AppSettings["LimitNum"].ToString()); //打折票数量 int discountNum = ticketAmount; //超出票数量 int overstepNum = 0; //总金额 double money = 0; //购票总数是否多出购票限定数量 if (ticketAmount > limitNum) { discountNum = limitNum; overstepNum = ticketAmount - limitNum; } money = unitPrice * discountNum * 0.5 + unitPrice * overstepNum; return money; } } }
DiamondStrategy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Configuration; namespace StrategyPatterns { /// <summary> /// 钻石卡算法 /// </summary> public class DiamondStrategy : IStrategy { /// <summary> /// 计算方法 /// </summary> /// <param name="ticketAmount">购票数量</param> /// <param name="unitPrice">单价</param> /// <returns>总金额</returns> public double Algorithm(int ticketAmount, double unitPrice) { //购票限定数量 int limitNum = int.Parse(ConfigurationManager.AppSettings["LimitNum"].ToString()); //打折票数量 int discountNum = ticketAmount; //超出票数量 int overstepNum = 0; //总金额 double money = 0; //购票总数是否多出购票限定数量 if (ticketAmount > limitNum) { discountNum = limitNum; overstepNum = ticketAmount - limitNum; } money = unitPrice * discountNum * 0.6 + unitPrice * overstepNum; return money; } } }
GoldStrategy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Configuration; namespace StrategyPatterns { /// <summary> /// 金卡算法 /// </summary> public class GoldStrategy : IStrategy { /// <summary> /// 计算方法 /// </summary> /// <param name="ticketAmount">购票数量</param> /// <param name="unitPrice">单价</param> /// <returns>总金额</returns> public double Algorithm(int ticketAmount, double unitPrice) { //购票限定数量 int limitNum = int.Parse(ConfigurationManager.AppSettings["LimitNum"].ToString()); //打折票数量 int discountNum = ticketAmount; //超出票数量 int overstepNum = 0; //总金额 double money = 0; //购票总数是否多出购票限定数量 if (ticketAmount > limitNum) { discountNum = limitNum; overstepNum = ticketAmount - limitNum; } money = unitPrice * discountNum * 0.7 + unitPrice * overstepNum; return money; } } }
SilverStrategy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Configuration; namespace StrategyPatterns { /// <summary> /// 银卡算法 /// </summary> public class SilverStrategy : IStrategy { /// <summary> /// 计算方法 /// </summary> /// <param name="ticketAmount">购票数量</param> /// <param name="unitPrice">单价</param> /// <returns>总金额</returns> public double Algorithm(int ticketAmount, double unitPrice) { //购票限定数量 int limitNum = int.Parse(ConfigurationManager.AppSettings["LimitNum"].ToString()); //打折票数量 int discountNum = ticketAmount; //超出票数量 int overstepNum = 0; //总金额 double money = 0; //购票总数是否多出购票限定数量 if (ticketAmount > limitNum) { discountNum = limitNum; overstepNum = ticketAmount - limitNum; } money = unitPrice * discountNum * 0.8 + unitPrice * overstepNum; return money; } } }
App.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <!-- 购票限定数量 --> <add key="LimitNum" value="4"/> </appSettings> </configuration>
Context.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace StrategyPatterns { /// <summary> /// 算法选择类 /// </summary> public class Context { IStrategy myStrategy = null; /// <summary> /// 构造函数 /// </summary> /// <param name="strategy">算法类</param> public Context(IStrategy strategy) { myStrategy = strategy } /// <summary> /// 获得购票总金额 /// </summary> /// <param name="ticketAmount">购票数量</param> /// <param name="unitPrice">单价</param> /// <returns>总金额</returns> public double GetMoney(int ticketAmount, double unitPrice) { return myStrategy.Algorithm(ticketAmount, unitPrice); } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace StrategyPatterns { class Program { static void Main(string[] args) { Console.WriteLine("变形金刚电影票80元一张"); Console.WriteLine("用至尊卡购买7张变形金刚的电影票:"); Context context = new Context(new AceCardStrategy()); Console.WriteLine("总金额:" + context.GetMoney(7, 80).ToString() + "元"); Console.WriteLine("用银卡购买3张变形金刚的电影票:"); context = new Context(new SilverStrategy()); Console.WriteLine("总金额:" + context.GetMoney(3, 80).ToString() + "元"); } } }
运行结果:
万达影城还有其它的销售策略,如星期二全场半价、星期四女性同胞半价,只需为每种策略增加一个算法类实现算法接口。
再来对策略进行一下总结:
1. 策略模式就是将算法与其宿主类进行分离。
2. 算法与算法之间相对独立,这些算法完成的工作都相同,只是实现不同。
策略模式使用场景:
1. 存在许多完成的工作相同,只是实现不同的类。
2. 要实现某个给定的目的存在许多种不同的算法。
3. 算法中存在客户程序不应该访问到的数据。
真想在资料最后给小刘写上几句暧昧的话,快乐的一天过去了,明天又得上班了,可怜的上班族啊!!!
文章源代码:
下载
从生活中的点点滴滴认识设计模式系列文章:
1. 从生活中的点点滴滴认识设计模式1-装饰器模式(Decorator Pattern)
2. 从生活中的点点滴滴认识设计模式2-策略模式(Strategy Patten)
3. 从生活中的点点滴滴认识设计模式3-单件模式(Singlegon Patten)