
定义:策略模式(Strategy Pattern)是一种行为型模式。在这个模式中,会定义一组算法类,将每个算法实现分别封装起来,让它们可以互相替换
解释:在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。在策略模式中,我们创建表示各种策略对象和一个行为随着策略对象的改变而改变的 context 对象。不同的策略对象决定不同的 context 对象的执行算法。
策略模式主要用于解决:
使用场景:
实现方式:
常见应用场景:
优点:
缺点:
使用建议:
策略模式包含以下几个主要角色:
我们将创建一个定义活动的 Strategy 接口和实现了 Strategy 接口的实体策略类。Context 是一个使用了某种策略的类
我们在 main 方法中使用 Context 上下文对象和策略对象来演示 Context 在它所配置或使用的策略发送改变时的行为变化

/**
* @Description 策略接口
* @Author Mr.Zhang
* @Date 2025/5/6 0:36
* @Version 1.0
*/
public interface Strategy {
// 具体的操作由策略类实现
int doOperation(int num1, int num2);
}/**
* @Description 加法操作
* @Author Mr.Zhang
* @Date 2025/5/6 0:38
* @Version 1.0
*/
public class OperationAdd implements Strategy {
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}/**
* @Description 减法操作
* @Author Mr.Zhang
* @Date 2025/5/6 0:38
* @Version 1.0
*/
public class OperationSubtract implements Strategy {
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}/**
* @Description 乘法操作
* @Author Mr.Zhang
* @Date 2025/5/6 0:38
* @Version 1.0
*/
public class OperationMultiply implements Strategy {
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}/**
* @Description 工厂类,用来创建策略对象
* @Author Mr.Zhang
* @Date 2025/5/7 21:34
* @Version 1.0
*/
public class StrategyFactory {
private Strategy strategy;
public StrategyFactory(Strategy strategy) {
this.strategy = strategy;
}
public int execute(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}/**
* @Description TODO
* @Author Mr.Zhang
* @Date 2025/5/7 21:37
* @Version 1.0
*/
public class Main {
public static void main(String[] args) {
StrategyFactory factory = new StrategyFactory(new OperationAdd());
System.out.println("10 + 5 = " + factory.execute(10, 5));
factory = new StrategyFactory(new OperationSubtract());
System.out.println("10 - 5 = " + factory.execute(10, 5));
factory = new StrategyFactory(new OperationMultiply());
System.out.println("10 * 5 = " + factory.execute(10, 5));
}
}输出
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50至此,我们已经学会了策略模式的使用。那下面我将再举一个我实际开发中用到的在对接第三方支付时使用到的策略模式的例子
假设我们要做一个多支付方式扣款的功能,需求如下:
针对这个需求,如果我们直接使用 if...else... 来实现的话无论是可读性还是可维护性都特别低,复杂度较高。那我们完全可以采用 策略模式 + 工厂模式 来进行优化
/**
* @author ZGM
* 支付策略接口
*/
public interface PayStrategy {
/**
* 优惠后支付金额
*/
long discountPayMoney(Long money, Integer plat);
}/**
* 微信支付
*/
@Slf4j
@Component("weChatPay")
public class WeChatPayStrategy implements PayStrategy {
/**
* 优惠后支付金额
* @param money
* @param plat
*/
@Override
public long discountPayMoney(Long money, Integer plat) {
long price=money;
price-=50;
if(订单金额>=50元){
price-=100;
}else if(订单金额>=30元){
price-=50;
}
return price;
}
}/**
* 银联支付
*/
@Slf4j
@Component("unionpayPay")
public class UnionpayPayStrategy implements PayStrategy {
/**
* 优惠后支付金额
*
* @param money
* @param plat
*/
@Override
public long discountPayMoney(Long money, Integer plat) {
long price=money;
price-=100;
return price;
}
}/**
* 支付宝支付
*/
@Slf4j
@Component("alipayPay")
public class AlipayPayStrategy implements PayStrategy {
/**
* 优惠后支付金额
*
* @param money
* @param plat
*/
@Override
public long discountPayMoney(Long money, Integer plat) {
long plat=money;
price-=70;
if(订单金额大于>=80元){
price-=200;
}else if(订单金额>=40){
price-=70;
}
return price;
}
}/**
*工厂类
*/
@Service
@Slf4j
public class PayFactory {
@Autowired
Map<String, PayStrategy > map = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
// 在此处将策略类的实例添加到 map 中
map.put("alipay", new AliPayStrategy());
map.put("wechatpay", new WeChatPayStrategy());
// ...
}
public PayStrategy getStrategy(String componentName) {
PayStrategy strategy= map.get(componentName);
if (strategy == null) {
log.error("没有获取工厂类 componentName={}", componentName);
return null;
}
return strategy;
}
}@RestController
public class TestController {
@Autowired
PayFactory payFactory;
@RequestMapping(value = "test")
public Long test(Integer plat) {
// plat==0 微信 ,1银联,2支付宝
// 因为策略类组件名不能重复所以我们最好是做一个常量池来进行类型转换.这里就不一一去写了.
PayStrategy alipayPay = payFactory.getStrategy("alipayPay");
Long price = alipayPay.discountPayMoney(10000L);
return price;
}
}输出
