需求:当在程序设计中,未来我们的算法以及一些规则需要根据业务的内容进行添加以及频繁变更,需要尽量减少代码的变更,以便于不影响客户的使用。
问题:采用传统的编写代码方式编写程序会造成程序维护性和扩展性的下降,客户端代码会出现大量的判断语句,造成代码的重复,不便于算法类和使用算法类的解耦。
解决方案:采用策略模式,定义抽象算法类Strategy,然后将具体的算法方法封装在继承于Strategy的具体类中,然后定义一个上下文Context,将Strategy的具体实例对象传入Context的构造方法之中,然后定义方法根据具体的策略对象,调用其算法的方法。策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响使用算法的客户。
例子:超市收银软件,超市的活动如打折或者积分会使价钱发生变化。未来还有可能出现新的活动方式,所以程序的算法经常需要进行添加以及修改。所以可以采取策略模式。
以下实现伪代码:
//定义算法的父类。
abstract class CashSuper{
public abstract double acceptCash(double money);
}
//正常收费算法
class CashNormal extends CashSuper{
public double acceptCash(double money){
return money;
}
}
//打折算法
class CashRebate extends CashSuper{
private double moneyRebate=1d;
public CashRebate(String moneyRebate){
this.moneyRebate=double.Parse(moneyRebate);
}
public double acceptCash(double money){
return money*moneyRebate;
}
}
//还有很多的算法,根据具体的业务进行添加新类 这里不一一列举了。
//定义上下文Context
class cashContext{
private CashSuper cs;
//通过构造方法 传入具体的策略
public CashContext(CashSuoer csper){
this.cs=csper;
}
public double getResult(double money){
return cs.acceptCash(money);
}
}
//客户端代码
double total=0.0d;//用于计算总价钱
CashContext cc=null;
switch("收费规则") { //收费规则填写根据具体的业务进行变化,这里有“正常收费”和“打折”
case "正常收费":
cc=new CashContext(new CashNormal());
break;
case "打八折":
cc=new CashContext(new CashRebate("0.8"));
break;
}
double totalPrices=0;
totalPrices=cc.getResult(3200) //括号中填写的是具体收了多少钱
这里就把具体的价钱算出来的 ,策略模式的好处可以看出来,算法和客户端进行了分离,使客户端只需要接触一个context类就可以进行具体业务的计算,减少了算法和使用算法类之间的耦合。但是这里有一个缺点就是把具体判断使用哪个算法的选择权给了客户端,这里可以结合使用简单工厂模式将客户端的选择权进行转移。只需要将context类进行一下改造
class cashContext{
private CashSuper cs=null;
//通过构造方法 传入具体的策略
public CashContext(String type){ //type参数是一个字符串,表示收费类型
switch(type) {
case "正常收费":
CashNormal cs0=new CashNormal();
cs=cs0
break;
case "打八折":
CashRebate cr2=new CashRebate("0.8");
cs=cr2;
break;
}
}
public double getResult(double money){
return cs.acceptCash(money);
}
}
将Context类也可以看成一个工厂,进行对象的实例化,并且Context类还对算法家族的算法进行了具体的调用。这样客户端就不需要进行类型的判断,客户端只需要进行类型的选择传入就可以了。
总结:策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的工作都是相同的工作,只是具体的实现不同,他们以相同的方式进行算法的调用,减少了算法类和使用算法类之间的耦合。策略模式可以用来封装几乎任何类型的规则。