当前位置: 首页 > news >正文

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

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

策略模式(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机制
策略执行顺序依赖策略之间存在依赖关系引入策略责任链模式

相关文章:

  • Unity-Mirror网络框架-从入门到精通之Multiple Additive Scenes示例
  • iOS主要知识点梳理回顾-5-运行时方法交换
  • Jmeter+Influxdb+Grafana平台监控性能测试过程
  • STM32F407通过FSMC扩展外部SRAM和NAND FLASH
  • Gitlab中如何进行仓库迁移
  • 游戏应用谷歌后台使用介绍
  • 设计模式Python版 命令模式(上)
  • conda 修复 libstdc++.so.6: version `GLIBCXX_3.4.30‘ not found 简便方法
  • 如何在Servlet容器中使用HttpServletResponse?
  • 【Mybatis】动态 SQL:代码与数据的灵动共舞,奏响数据库查询的华丽乐章
  • day9手机创意软件
  • 小程序canvas2d实现横版全屏和竖版逐字的签名组件(字帖式米字格签名组件)
  • Java面试题总结 - Java多线程篇(附答案)
  • Open Liberty使用指南及微服务开发示例(二)
  • DataBase【MySQL基础夯实使用说明(下)】
  • 在软件产品从开发到上线过程中,不同阶段可能出现哪些问题,导致软件最终出现线上bug
  • 网络安全之探险
  • Python Pandas(7):Pandas 数据清洗
  • Log4j定制JSON格式日志输出
  • 常用共轭先验分布
  • 新村回响:一周城市生活
  • 深圳两家会所涉卖淫嫖娼各被罚7万元逾期未缴,警方发催告书
  • 重温经典|《南郭先生》:不模仿别人,不重复自己
  • 公示!17个新职业、42个新工种亮相
  • 吴清稳市场稳预期发布会十要点:谈平准基金、股市稳定、公募改革和巴菲特
  • 川大全职引进考古学家宫本一夫,他曾任日本九州大学副校长