前言:
这次写博客改变了以往写博客的方式,以前都是敲完代码再来总结书中的内容,但是这次首先将策略模式的一些基本知识总结了,然后去敲代码,这样的顺序有一个好处,敲代码的时候能很清楚的知道自己往哪走,知道这些代码的功能是什么。看来博客专家都是在一次一次推翻自己,又一次一次有新的历程中成长的!
策略模式
what:
策略模式(strategy):是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。此模式让算法的变化,不会影响到使用算法的客户。
情景:
大鸟为了进一步提高小菜,让小菜做了一个商场收银软件,营业员根据客户所购买的商品的单价和数量,向客户收费。
小菜三下五除二又交了份作业,这次代码规范问题倒是没有再犯,但是当大鸟需要价格打8折的时候, 小菜还胸有成竹的说乘以0.8就可以了,那么,每次活动打折结束都要重新改一遍程序代码吗?这下小菜可明白了,加一个下拉选择框就可以了。
那么这时候又有问题了,下拉框中的内容重复代码太多,而且如果我不打8折,改成买300返100了怎么办?所以这里又用到了之前学的简单工厂模式。将所有的打折算法都放到一个类里面。这里需要有一个现金收费抽象类,一个正常收费子类,一个打折收费子类,一个返利收费子类,一个现金收费工厂类,和客户端程序。
但是,简单工厂模式虽然能解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包括了所有的收费方式,商场可能经常性的修改打折额度等,每次维护或扩展都要改动这个工厂,以至代码需重新编译部署,所以我们又学习到一个模式:策略模式。
应用:
1.策略模式是用来封装算法的,但再实践中,我们可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不用的业务规则,我们都可以考虑使用策略模式处理这种变化的可能性。
2. 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。
代码展示:
现金收费抽象类:
abstract class CashSuper
{
//收取现金,参数为原价,返回为当前价。
public abstract double acceptCash(double money);
}
正常收费子类:
class CashNormal:CashSuper //正常收费子类
{
public override double acceptCash(double money) //重写
{
return money;
}
}
打折收费子类:
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;
}
}
返利收费子类:
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;
}
}
策略与简单工厂结合:
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"打8折":
CashRebate cr2 = new CashRebate("0.8");
cs = cr2;
break;
}
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
客户端代码:
设计好自己想要的页面,写入自己想要的效果,调用模式就OK啦。这里就不多展示了。
下面来看一下策略模式的基本代码:
strategy类,定义所有支持的算法的公共接口:
abstract class Strategy //抽象算法类
{
public abstract void AlgorithmInterface(); //算法方法
}
ConcreteStrategy,封装了具体的算法或行为,继承于strategy:
class ConcreteStrategy:Strategy //封装了具体的方法或行为,
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法A实现");
}
}
class ConcreteStrategyB : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法B实现");
}
}
class ConcreteStrategyC : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法C实现");
}
}
context,用一个ConcreteStrategy来配置,维护一个对strategy对象的引用
class Context //上下文
{
Strategy strategy;
public Context(Strategy strategy) //初始化时,传入具体的策略对象
{
this.strategy = strategy;
}
//上下文接口
public void ContextInterface() //根据具体的策略对象,调用其算法的方法
{
strategy.AlgorithmInterface();
}
}
后记
学习一遍对于策略模式也是一知半解,以后还会深入运用的,放到实践中。