策略模式简介及应用场景

关于策略模式在编码过程中的应用,这是一篇跟AI对话得出的学习文章,欢迎交流~

策略模式简介及应用场景:☀️☀️☀️

1. 策略模式(Strategy Pattern)核心解读

策略模式是行为型设计模式的核心之一,定义为:

定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。此模式让算法的变化独立于使用算法的客户。

1.1 通俗理解

把“完成同一任务的不同方法”(比如支付可选择微信、支付宝)抽离为独立的“策略类”,主逻辑(支付流程)只需调用统一接口,切换方法时无需修改主逻辑。

1.2 核心角色(3个)

角色作用
环境类(Context)持有策略对象引用,提供统一调用入口,不负责选择具体策略(也可负责)
抽象策略(Strategy)定义所有具体策略必须实现的接口/抽象类(如支付的 pay() 方法)
具体策略(ConcreteStrategy)实现抽象策略,封装具体算法(如微信支付、支付宝支付的逻辑)

1.3 核心优势

  • 开闭原则:新增策略无需修改原有代码,仅需新增类;
  • 消除冗余 if-else:避免主逻辑中大量条件分支的臃肿代码;
  • 代码复用+可测试:每个策略独立封装,可单独测试、复用;
  • 动态切换:运行时可根据条件切换策略(如用户选择支付方式后自动匹配)。

2. 策略模式在Java中的典型示例(支付场景)

以“支付方式选择”为例,对比不用策略模式用策略模式的实现。

2.1 反例:不用策略模式(臃肿if-else)

text
复制代码
// 主逻辑耦合所有支付方式,新增/修改需改代码 public class PaymentService { public void pay(String payType, BigDecimal amount) { if ("WECHAT".equals(payType)) { System.out.println("微信支付:" + amount + "元"); // 微信支付的SDK调用、签名等逻辑(数百行) } else if ("ALIPAY".equals(payType)) { System.out.println("支付宝支付:" + amount + "元"); // 支付宝支付的逻辑(数百行) } else if ("BANK".equals(payType)) { System.out.println("银行卡支付:" + amount + "元"); } else { throw new IllegalArgumentException("不支持的支付方式"); } } } // 调用方 public class Client { public static void main(String[] args) { PaymentService service = new PaymentService(); service.pay("WECHAT", new BigDecimal("100")); } }

问题

  • 新增支付方式需修改核心方法,违反开闭原则;
  • 代码臃肿,维护成本高;
  • 支付逻辑无法单独测试、复用。

2.2 正例:用策略模式重构(大厂标准写法)

步骤1:定义抽象策略(支付接口)

text
复制代码
// 所有支付方式的统一接口 public interface PaymentStrategy { void pay(BigDecimal amount); // 支付方法 String getPayType(); // 获取支付类型(用于匹配) }

步骤2:实现具体策略(各支付方式)

text
复制代码
// 微信支付策略 public class WechatPayment implements PaymentStrategy { @Override public void pay(BigDecimal amount) { System.out.println("【微信支付】发起支付,金额:" + amount + "元"); // 微信SDK调用、签名等逻辑 } @Override public String getPayType() { return "WECHAT"; } } // 支付宝支付策略 public class AlipayPayment implements PaymentStrategy { @Override public void pay(BigDecimal amount) { System.out.println("【支付宝支付】发起支付,金额:" + amount + "元"); // 支付宝SDK调用、验签等逻辑 } @Override public String getPayType() { return "ALIPAY"; } } // 银行卡支付策略 public class BankPayment implements PaymentStrategy { @Override public void pay(BigDecimal amount) { System.out.println("【银行卡支付】发起支付,金额:" + amount + "元"); // 银行接口调用、身份验证等逻辑 } @Override public String getPayType() { return "BANK"; } }

步骤3:定义环境类(统一入口)

text
复制代码
// 封装策略的统一调用入口 public class PaymentContext { // 策略容器:缓存所有支付策略 private static final Map<String, PaymentStrategy> STRATEGY_MAP = new HashMap<>(); // 静态初始化策略 static { STRATEGY_MAP.put(new WechatPayment().getPayType(), new WechatPayment()); STRATEGY_MAP.put(new AlipayPayment().getPayType(), new AlipayPayment()); STRATEGY_MAP.put(new BankPayment().getPayType(), new BankPayment()); } // 外部统一调用方法 public void pay(String payType, BigDecimal amount) { PaymentStrategy strategy = STRATEGY_MAP.get(payType); if (strategy == null) { throw new IllegalArgumentException("不支持的支付方式:" + payType); } strategy.pay(amount); } // 动态添加新策略 public void addStrategy(PaymentStrategy strategy) { STRATEGY_MAP.put(strategy.getPayType(), strategy); } }

步骤4:调用方使用(极简)

text
复制代码
public class Client { public static void main(String[] args) { PaymentContext context = new PaymentContext(); context.pay("WECHAT", new BigDecimal("100")); // 微信支付 context.pay("ALIPAY", new BigDecimal("200")); // 支付宝支付 // 新增策略(无需修改原有代码) // context.addStrategy(new UnionPayPayment()); // context.pay("UNION", new BigDecimal("300")); } }

输出结果

text
复制代码
【微信支付】发起支付,金额:100元 【支付宝支付】发起支付,金额:200元

2.3 Spring环境下的进阶写法(大厂实战)

结合注解+自动注入,无需手动维护策略容器:

text
复制代码
// 1. 定义策略注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface PayStrategy { String value(); // 支付类型 } // 2. 具体策略添加注解+交给Spring管理 @PayStrategy("WECHAT") @Component public class WechatPayment implements PaymentStrategy { /* 实现方法 */ } @PayStrategy("ALIPAY") @Component public class AlipayPayment implements PaymentStrategy { /* 实现方法 */ } // 3. 环境类自动加载策略 @Component public class PaymentContext { private final Map<String, PaymentStrategy> strategyMap; // Spring自动注入所有PaymentStrategy类型的Bean public PaymentContext(List<PaymentStrategy> strategies) { strategyMap = new HashMap<>(); for (PaymentStrategy strategy : strategies) { String payType = strategy.getClass().getAnnotation(PayStrategy.class).value(); strategyMap.put(payType, strategy); } } // 支付方法(同上) public void pay(String payType, BigDecimal amount) { /* 逻辑同上 */ } } // 4. 业务层调用 @Service public class OrderService { @Autowired private PaymentContext paymentContext; public void createOrder(String payType, BigDecimal amount) { // 订单逻辑... paymentContext.pay(payType, amount); } }

3. 策略模式的典型应用场景(大厂高频)

除支付场景外,策略模式在大厂项目中的核心应用:

3.1 业务规则动态切换

  • 场景:电商优惠策略(满减、折扣、优惠券)、物流配送策略(顺丰、京东);
  • 实现:每种规则封装为策略类,下单时根据订单信息动态匹配。

3.2 算法/接口适配

  • 场景:消息推送(短信、钉钉、企业微信)、OSS存储(阿里云、腾讯云);
  • 实现:每种推送/存储方式封装为策略,核心逻辑通过统一接口调用。

3.3 框架内置的策略模式

大厂常用框架大量使用策略模式:

  • JDKComparator(排序策略)、ThreadPoolExecutor的拒绝策略;
text
复制代码
// Comparator的策略模式应用 List<Integer> list = Arrays.asList(3,1,2); list.sort(Comparator.naturalOrder()); // 升序策略 list.sort(Comparator.reverseOrder()); // 降序策略
  • SpringResource(资源加载策略)、HandlerMapping(请求映射策略)。

4. 大厂为什么重视设计模式?

很多新手认为设计模式是“花架子”,但大厂对其重视程度极高,核心原因:

4.1 解决大规模代码的维护性问题

大厂项目代码量可达百万行,人员流动频繁:

  • 无设计模式:代码是“面条式”if-else,新人接手需逐行读代码,改一行崩一片;
  • 有设计模式:代码遵循统一规范(如策略模式的“接口+实现”),新人快速理解,维护成本降低80%。

4.2 支撑高扩展的业务需求

大厂业务迭代极快(如电商每年新增N种支付方式):

  • 无设计模式:新增功能需修改核心代码,风险高;
  • 有设计模式:新增策略仅需加新类,符合“开闭原则”,上线风险几乎为0。

4.3 实现代码复用+标准化

大厂强调“不重复造轮子”:

  • 策略模式将通用逻辑封装为独立类,可在多模块复用;
  • 设计模式是“程序员的通用语言”,说“这里用策略模式”,团队全员理解代码结构,沟通成本降低。

4.4 适配高并发/高可用架构

策略模式的“解耦”特性是高并发架构的基础:

  • 支付场景:可按支付类型路由到不同线程池/服务器,实现分流;
  • 存储场景:可按数据量切换存储介质(内存/磁盘/OSS),提升性能。

5. 总结

  • 策略模式核心:封装算法为独立策略,解耦“使用逻辑”与“具体实现”;
  • 典型应用:支付、优惠、推送、存储适配等需动态切换逻辑的场景;
  • 大厂价值:维护性(易读易改)、扩展性(新增功能不碰旧代码)、复用性(策略类可复用);
  • 避坑点:若策略少于2个且永不扩展,无需使用(避免过度设计)。
0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
她和夏天一样热
作者分享
工厂方法模式简介及应用场景
3
Spring 源码入门篇
4
入职dayone 刚开始还庆幸这家还好是纯springboot那一套框架开发, 但是进来发现整个开发部就四个人,而且目前这个项目完全是由实习生自己开发的,而且是口头给需求,感觉有点小压力, 毕竟之前没实习过,基本没人带,现在就只能靠另外一个实习的哥们帮忙带一下(他在里面干了三四个月好像也快离开了) 而且今天给了一个小需求,然后要我们自己设计新的表😂 目前想法就是先顶住压力干三个月 后面再找找机会 或者等明年春招,这个思路可以嘛? 还有 问一下已经有过实习经历的友友,有没有建议给到我刚入职的萌新, 像给我一个需求 ,我是先去捋一下思路,需要设计表,哪些字段,还有返回给前端什么数据这些 ,是不是得先想好啊, 项目负责人都没告诉我,就是直接口头给需求 然后我们开发就行😭 现在脑子懵,希望有经验的友友给点建议,平时拿到一个需求是怎么开发的呢
3
用宝塔面板部署的项目,现在报连接不上redis 是什么原因呢?我本身项目代码是没问题的 在本地能正常连接,但是怎么连不上宝塔上面下的reids呢?之前还可以 然后后面项目线上报错我就重新删了再搞 结果就报连接不是redis了,配置密码也没问题呀。有大佬有遇到这种问题嘛,求助!
2
#云图库扩展点 #AI上传优化为消息队列异步执行 有大佬已经完成了这个拓展点了吗,求助!!! 消息队列是这两天看Bi项目的文档笔记现学的。 然后拉bi项目的源码看。搞了一个早上,思路很乱,不清楚生产者跟消费者具体要传什么message,晕了 先吃个饭 下午再整理一下思路,希望有大佬能指点一下😭
4
下载 APP