前言
什么是设计模式?说白了就是套路,是经过历代程序员总结出来的。很多时候我们虽然学会了很多套路,但是啥时候使用,使用哪个合适,我想这才是问题的关键。
知道怎么用不知道什么时候用,这时候看下代码风格也行用的上,策略模式是非常容易通过代码风格使用上的。
策略模式,为什么叫策略模式呢?其实策略模式还有一个别名叫做政策(policy)模式,在古代,对不同的国家呢,实行不同的政策,对A呢,采取税务10%,对B国采取税务20%。
这样根据不同国家政策不同呢,在计算机中就是根据不同对象采取不同的方法,就叫做策略模式咯。但是呢,如果直接采用if else 这种行为呢,人们发现过于臃肿,且复用性极差,那么就形成了这样一种模式去缓解这个问题。
策略模式属于对象行为模式,其实不去看概念也很好记,在运行时针对不同对象,去做出相应的行为。至于为什么不分到结构型或者其他型,只是它更符合行为型,一个类的行为或其算法可以在运行时更改,这些分类其实没有绝对的界限,只是有权威人士对其进行了规划。
那么策略模式的风格是什么,查看正文。
开车出发
public enum PolicyBase
{
US_Policy,
DE_Policy,
FR_Policy
}
public class Strategy
{
PolicyBase policyBase;
public Strategy(PolicyBase policyBase) {
this.policyBase = policyBase;
}
public double CalculatePolicy() {
if (policyBase == PolicyBase.US_Policy)
{
return 0.9;
}
else if (policyBase == PolicyBase.DE_Policy)
{
return 0.8;
}
else if (policyBase == PolicyBase.FR_Policy)
{
return 0.1;
}
return 0;
}
}
根据不同的国家,采取了不同的政策。这样一看好像没有啥问题啊,根据了不同国家制定了不同税法。
但是呢,在开发代码的时间轴上,也就是未来的角度上存在的极大的问题。比如和英国(GB)合作了,我得改吧?然后又和另外一个国家合作了,恐怕又得来一遍。
这时候有人就纳闷了,还想不改代码?代码的确是要改的,但是不能违法了封闭开发原则。
在红色部分呢,是我们需要继续往下添加代码的地方,也就是我们加一个国家就需要把我们写过的任何一个区域改一遍。
我想这就很糟糕了,牵扯太大,对于发布来说就需要测试整个子模块,我想这代价无法让人接受,这时候策略者模式就出现了。
public enum PolicyBase
{
US_Policy,
DE_Policy,
FR_Policy
}
public interface Policy
{
double Calculate();
}
public class USPolicy : Policy
{
public double Calculate()
{
throw new NotImplementedException();
}
}
public class DEPolicy : Policy
{
public double Calculate()
{
throw new NotImplementedException();
}
}
public class FRPolicy : Policy
{
public double Calculate()
{
throw new NotImplementedException();
}
}
public class StrategyFactory{
Policy policy;
public StrategyFactory(PolicyBase policyBase) {
switch (policyBase)
{
case PolicyBase.US_Policy:
policy = new USPolicy();
break;
case PolicyBase.DE_Policy:
policy = new DEPolicy();
break;
case PolicyBase.FR_Policy:
policy = new FRPolicy();
break;
}
}
public Policy GetPolicy() {
return policy;
}
}
class SalesOrder
{
private Policy Policy;
public SalesOrder(StrategyFactory strategyFactory)
{
this.Policy = strategyFactory.GetPolicy();
}
public double CalculatePolicy()
{
double val = Policy.Calculate();
return val;
}
};
上述代码中,通过策略者模式把原来的获取各国的税法比例变成了SalesOrder类,而这个类不再改变,也就是说所以依赖于获取各国税法参数的将依赖于一个稳定的类。
这时候很多纳闷了,如果我需要添加一个英国(GB),依然需要在红色部分就行修改啊,修改的地方如下:
修改的地方一样多,且还要多加一个GBPolicy类,这不是白忙活了吗?
首先我们来看下前后依赖关系图:
使用策略模式前:
使用策略模式后:
这样一看,不仅是没有啥好处,还复杂了。
然而这样一想,我们处理的是解决这个税法问题这个业务上,可以肯定的就是使用策略模式后,我下面红框部分稳定了,也就是在二进制上可以复用,但是上面红色部分倒是有问题了,耦合太大。
但是呢,我们知道上面复杂部分其实就是简单工厂模式,问题就回到了如何优化简单工厂模式了,如果能解决上面红框的问题,那么是可行的。
由于篇幅有限,下一篇总结工厂模式到抽象工厂到反射这个演化。
这时候我们看到了,如果遇到了if else 且以后会增加else if,可以用策略模式,去缓解这个问题,增加代码复用性。
但是稳定的if else 呢是不需要的,比如说星期一到星期日,这种就是稳定的了,本来处于稳定的,那么其改变的价值就不是很大。
uml图
后续补上
总结
策略模式的作用,解决使用不稳定 的if...else 所带来的复杂和难以维护。