深度解析策略模式:从理论到企业级实战应用

一、策略模式的本质:面向接口的算法工厂

策略模式(Strategy Pattern)是行为型设计模式的典型代表,其核心思想是将算法族抽象为独立对象,使其能够相互替换。这种模式完美体现了以下面向对象设计原则:

  1. 开闭原则(OCP):新增策略无需修改已有代码

  2. 单一职责原则(SRP):每个策略只负责特定算法

  3. 依赖倒置原则(DIP):高层模块依赖抽象而非具体实现

UML类图


二、策略模式的三种典型实现方式

1. 基础版实现(传统方式)

复制代码
// 策略接口
public interface DiscountStrategy {
    BigDecimal calculateDiscount(BigDecimal amount);
}

// 具体策略
public class VipDiscount implements DiscountStrategy {
    @Override
    public BigDecimal calculateDiscount(BigDecimal amount) {
        return amount.multiply(new BigDecimal("0.8"));
    }
}

public class FestivalDiscount implements DiscountStrategy {
    @Override
    public BigDecimal calculateDiscount(BigDecimal amount) {
        return amount.subtract(new BigDecimal("50"));
    }
}

// 上下文环境
public class OrderContext {
    private DiscountStrategy strategy;

    public void setStrategy(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    public BigDecimal executeDiscount(BigDecimal amount) {
        return strategy.calculateDiscount(amount);
    }
}

2. 枚举策略(简化分支判断)

复制代码
public enum CalculatorStrategy {
    ADD {
        @Override
        public int execute(int a, int b) { return a + b; }
    },
    SUBTRACT {
        @Override
        public int execute(int a, int b) { return a - b; }
    };

    public abstract int execute(int a, int b);
}

3. Spring集成版(企业级实践)

复制代码
// 定义策略接口
public interface PaymentStrategy {
    void processPayment(BigDecimal amount);
}

// 实现策略(带Spring注解)
@Component("alipayStrategy")
public class AlipayStrategy implements PaymentStrategy {
    @Override
    public void processPayment(BigDecimal amount) {
        // 支付宝支付逻辑
    }
}

@Component("wechatPayStrategy")
public class WechatPayStrategy implements PaymentStrategy {
    @Override
    public void processPayment(BigDecimal amount) {
        // 微信支付逻辑
    }
}

// 策略上下文(自动注入策略集合)
@Service
public class PaymentContext {
    @Autowired
    private Map<String, PaymentStrategy> strategyMap;

    public void executePayment(String paymentType, BigDecimal amount) {
        PaymentStrategy strategy = strategyMap.get(paymentType + "Strategy");
        if (strategy != null) {
            strategy.processPayment(amount);
        } else {
            throw new IllegalArgumentException("Unsupported payment type");
        }
    }
}

三、策略模式的六大应用场景

场景1:电商促销系统

  • 满减策略

  • 折扣策略

  • 赠品策略

  • 积分抵现策略

场景2:支付网关路由

  • 支付宝支付

  • 微信支付

  • 银联支付

  • 数字货币支付

场景3:日志处理系统

  • 本地文件存储

  • 云存储(OSS/S3)

  • 消息队列转发

  • 数据库存储

场景4:数据校验引擎

  • 手机号校验

  • 身份证校验

  • 邮箱校验

  • 地址校验

场景5:游戏AI系统

  • 攻击策略

  • 防御策略

  • 逃跑策略

  • 补给策略

场景6:报表生成系统

  • PDF生成

  • Excel生成

  • HTML生成

  • CSV生成


四、策略模式与相关模式的深度对比

模式 关注点 与策略模式的关系
工厂模式 对象创建 策略模式常配合工厂创建具体策略
状态模式 状态转换 状态改变行为,策略改变算法
模板方法模式 算法步骤 策略替换整个算法,模板方法替换步骤
命令模式 请求封装 策略是主动选择,命令是被动触发

五、企业级实战:支付系统策略架构设计

架构图

复制

复制代码
[支付请求] --> [支付网关]
                   ↓
           [策略路由中心]
                   ↓
+----------------+----------------+
| 支付宝策略     | 微信支付策略    | 银联策略
+----------------+----------------+
                   ↓
           [渠道适配层]
                   ↓
          [第三方支付平台]

代码实现(Spring Boot +策略模式)

java

复制

复制代码
// 支付策略接口
public interface PaymentStrategy {
    PaymentResult pay(PaymentRequest request);
}

// 支付宝策略实现
@Component
public class AlipayStrategy implements PaymentStrategy {
    @Override
    @PaymentType(PayChannel.ALIPAY)
    public PaymentResult pay(PaymentRequest request) {
        // 调用支付宝SDK
        return new PaymentResult(true, "ALIPAY-123456");
    }
}

// 策略工厂(自动发现策略)
@Component
public class PaymentStrategyFactory {
    @Autowired
    private Map<String, PaymentStrategy> strategyMap;

    public PaymentStrategy getStrategy(PayChannel channel) {
        return strategyMap.values().stream()
                .filter(s -> s.getClass().isAnnotationPresent(PaymentType.class))
                .filter(s -> s.getClass().getAnnotation(PaymentType.class).value() == channel)
                .findFirst()
                .orElseThrow(() -> new RuntimeException("未找到支付策略"));
    }
}

// 支付服务
@Service
@RequiredArgsConstructor
public class PaymentService {
    private final PaymentStrategyFactory strategyFactory;

    public PaymentResult processPayment(PaymentRequest request) {
        PaymentStrategy strategy = strategyFactory.getStrategy(request.getChannel());
        return strategy.pay(request);
    }
}

六、策略模式的五个优化技巧

1. 策略预热缓存

复制代码
public class StrategyCache {
    private static final Map<String, Strategy> cache = new ConcurrentHashMap<>();

    public static Strategy getStrategy(String type) {
        return cache.computeIfAbsent(type, t -> {
            // 动态加载策略类
            try {
                return (Strategy) Class.forName(t).newInstance();
            } catch (Exception e) {
                throw new RuntimeException("策略加载失败");
            }
        });
    }
}

2. 策略权重配置

复制代码
# application.yml
payment:
  strategies:
    alipay: 
      weight: 60
      enable: true
    wechat: 
      weight: 30  
      enable: true
    unionpay: 
      weight: 10
      enable: false

3. 策略性能监控

复制代码
public class MonitoredStrategy implements Strategy {
    private final Strategy delegate;
    private final MeterRegistry registry;

    public MonitoredStrategy(Strategy delegate, MeterRegistry registry) {
        this.delegate = delegate;
        this.registry = registry;
    }

    @Override
    public void execute() {
        Timer.Sample sample = Timer.start(registry);
        try {
            delegate.execute();
        } finally {
            sample.stop(registry.timer("strategy.execution.time", "type", delegate.getClass().getSimpleName()));
        }
    }
}

七、常见陷阱与解决方案

陷阱 现象 解决方案
策略状态共享 线程安全问题 使用ThreadLocal或每次新建策略实例
策略膨胀失控 类数量爆炸 使用DSL动态生成策略类
策略切换开销大 频繁切换影响性能 引入策略缓存池
策略配置错误 运行时找不到策略 增加策略fallback机制
策略执行顺序依赖 策略之间存在依赖关系 引入策略责任链模式
相关推荐
ywf12151 小时前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
大阿明7 小时前
Spring Boot(快速上手)
java·spring boot·后端
哆啦A梦15888 小时前
Springboot整合MyBatis实现数据库操作
数据库·spring boot·mybatis
百锦再8 小时前
Java 并发编程进阶,从线程池、锁、AQS 到并发容器与性能调优全解析
java·开发语言·jvm·spring·kafka·tomcat·maven
星轨zb9 小时前
通过实际demo掌握SpringSecurity+MP中的基本框架搭建
数据库·spring boot·spring security·mp
NGC_661111 小时前
SSM vs SpringBoot+MyBatis 对比
spring
没有bug.的程序员12 小时前
Serverless 弹性扩容引发的全线熔断:Spring Boot 启动耗时从 1s 压缩至 0.3s 的物理级绞杀
java·spring boot·kubernetes·serverless·扩容·线上
深蓝轨迹13 小时前
@Autowired与@Resource:Spring依赖注入注解核心差异剖析
java·python·spring·注解
爱丽_13 小时前
Pinia 状态管理:模块化、持久化与“权限联动”落地
java·前端·spring
luom010214 小时前
SpringBoot - Cookie & Session 用户登录及登录状态保持功能实现
java·spring boot·后端