一、 定义
策略模式(Strategy)定义了一组算法,分别封装起来,让它们之间可以相互替换,使算法的变化不会影响到使用算法的用户。
策略模式封装了变化,如果需求是在不同的时间应用不同的业务规则,则可以考虑用策略模式,优点有:
1) 以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合
2) 简化了单元测试,每个算法有自己的类,可以通过自己的接口单独测试
二、 结构图
三、 示例代码
以商场收银为例,各种促销方式即各种总额计算方法。
//策略抽象类
package org.example.StrategyModel;
public abstract class Strategy {
public abstract double GetTotal();
}
//具体策略A
package org.example.StrategyModel;
public class SaleOff extends Strategy {
private double total;
private double saleoff;
SaleOff(double total,double saleoff){
this.total = total;
this.saleoff = saleoff;
}
@Override
public double GetTotal() {
return total * saleoff;
}
}
//具体策略B
package org.example.StrategyModel;
public class TotalReturn extends Strategy{
private double total;
private double returnMoney;
private double returnTotal;
TotalReturn(double total,double returnTotal,double returnMoney){
this.total = total;
this.returnMoney = returnMoney;
this.returnTotal = returnTotal;
}
@Override
public double GetTotal() {
if(total >= returnTotal)
return total + returnMoney;
else return total;
}
}
//策略相关类
package org.example.StrategyModel;
public class StrategyContext {
Strategy strategy=null;
StrategyContext(Strategy stt){
this.strategy = stt;
}
public double GetNewTotal(){
return strategy.GetTotal();
}
}
//测试类
package org.example.StrategyModel;
public class TestStrategy {
public static void main(String[] args) {
StrategyContext strategyContext = new StrategyContext(new SaleOff(350,0.5));
System.out.println(strategyContext.GetNewTotal());
}
}
四、 策略模式和简单工厂模式结合
两种模式的结合,将条件语句的判断隐藏到了Context类。
//策略上下文类,将策略类型判断封装到此类中,而不是放到客户端。简单工厂模式
package org.example.StrategyModel;
public class CashContext {
private double total;
private double saleoff;
CashContext(double total,double saleoff){
this.total = total;
this.saleoff = saleoff;
}
Strategy strategy = null;
public double GetLastTotal(String returnType){
switch (returnType){
case "sale": strategy = new SaleOff(total,saleoff);break;
case "more than 300": strategy = new TotalReturn(total,300,30);break;
default:break;
}
return strategy.GetTotal();
}
}
//测试类
package org.example.StrategyModel;
import java.util.Arrays;
public class TestCashFactory {
public static void main(String[] args) {
CashContext cc = new CashContext(350,0.8);
System.out.println(cc.GetLastTotal("sale"));
}
}