定义:它定义了算法家族,分别封装起来,让它们直接可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。
解决问题:解决代码中由多个if...else或switch case 带来的不易维护。
使用场景:不同的类只是由于具体行为的不同。比如在业务场景中有不同时间下有不同逻辑处理等。
核心思想:所有算法都是完成相同的工作,只是实现不同,可以以相同的方式调用所有的算法,减少各种算法类与使用算法类之间的耦合。
优点:1、算法(变化点)自由切换 2、降低if...else等判断语句的复杂度 3、扩展性好
缺点:策略类增多。
结构图:
包含的角色:
抽象策略角色(Stratege):用接口或抽象类定义,给出所有具体策略类所需要的方法。
具体策略角色(ConcreteStrategy):实现具体算法。
环境角色(Context):持有抽象策略Strategy的引用,可以动态修改持有的具体策略ConcreteStragety,给客户调用;
使用场景及代码实现:
需求:商场促销,存在各种打折优惠的方式,比如:打8折、满300减50或正常收费。每次根据购物的金额和当前的优惠手段,计算出应付多少。
具体分析:不管是什么优惠,都是一样的调用。唯一的变化点就是优惠的具体实现不同,在优惠手段变化时,只需要替换这个变化点即可。
代码:
抽象策略方法:
public interface Stratege {
public BigDecimal acceptAmount(BigDecimal amount);
}
具体策略方法:
public class StrategeNormal implements Stratege {//正常收费
@Override
public BigDecimal acceptAmount(BigDecimal amount) {
return amount;
}
}
public class StrategeRebate implements Stratege{//打折收费
public BigDecimal rebate = null;
public StrategeRebate(String rebate){
this.rebate = new BigDecimal(rebate);
}
@Override
public BigDecimal acceptAmount(BigDecimal amount) {
return rebate.multiply(amount);
}
}
public class StrategeReturn implements Stratege {//满300-50
private BigDecimal moneyCondition = null;
private BigDecimal moneyReturn = null;
public StrategeReturn(String moneyCondition,String moneyReturn) {
this.moneyCondition = new BigDecimal(moneyCondition);
this.moneyReturn = new BigDecimal(moneyReturn);
}
@Override
public BigDecimal acceptAmount(BigDecimal amount) {
if(amount.compareTo(moneyCondition)>-1) {
BigDecimal sBigDecimal = amount.divide(moneyCondition, 0,BigDecimal.ROUND_DOWN);
return amount.subtract(sBigDecimal.multiply(moneyReturn));
}else {
return amount;
}
}
}
上下文:
public class Context {
Stratege stratege;
public Context(Stratege stratege) {
this.stratege = stratege;
}
public BigDecimal ContextInterface(BigDecimal amount) {//上下文接口,根据具体的策略,调用对应的方法。
return stratege.acceptAmount(amount);
}
}
//在此场景下,将简单工厂模式和策略模式进行结合,减少客户端的判断压力
public class Context {
Stratege stratege;
public Context(String type) {
switch (type) {
case "正常收费":
stratege = new StrategeNormal();
break;
case "满300减50":
stratege = new StrategeReturn("300","50");
break;
case "8折":
stratege = new StrategeRebate("0.8");
break;
default:
break;
}
}
public BigDecimal ContextInterface(BigDecimal amount) {
return stratege.acceptAmount(amount);
}
}
测试代码:
public class StrategeTest {
public static void main(String[] args) {
Context context =null;
System.out.println("请输入优惠策略:");
Scanner scanner = new Scanner(System.in);
String stratege = scanner.nextLine();
Context context2 = new Context(stratege);
System.out.println("请输入金额:");
Scanner scanner2 = new Scanner(System.in);
String amount = scanner2.nextLine();
BigDecimal result = context2.ContextInterface(new BigDecimal(amount));
System.out.println(result);
}
}
总结:策略封装了变化(算法)。在简单工厂模式下,客户端需要认识Operation和OperationFactory两个类,而在策略模式中,客户端只需要知道Context ,耦合度更低。
注:案例出自《大话设计模式》