面试知识库
进阶

策略模式#

一句话答案#

定义算法族封装为独立类使其可互换,消除 if-else;Spring 中用 Map<String,Strategy> 注入所有实现按 type 选择。

核心要点

策略模式定义一系列算法,将每个算法封装成独立的类,使它们可以互相替换。客户端通过组合和委托的方式使用不同的策略。

传统 if/else 写法(反面教材):

public class NotificationService {
    public void send(String type, String message) {
        if ("sms".equals(type)) {
            // 发短信逻辑...
        } else if ("email".equals(type)) {
            // 发邮件逻辑...
        } else if ("push".equals(type)) {
            // 发推送逻辑...
        } else if ("wechat".equals(type)) {
            // 发微信逻辑...
        }
        // 每新增一种方式就要改这个方法,违反开闭原则
    }
}
java

策略模式重构:

策略模式 + Map/枚举分发的三板斧:

  1. 定义策略接口
  2. 每种算法实现一个策略类
  3. 用 Map(或枚举)做路由分发,消除 if/else

Java 中的策略模式实例:

  • Comparator —— 不同的比较策略传给 Collections.sort()
  • ThreadPoolExecutor 的拒绝策略 —— AbortPolicy/CallerRunsPolicy/DiscardPolicy
  • Spring Resource —— ClassPathResource/FileSystemResource/UrlResource
面试回答(2分钟版)

策略模式的核心是定义一组算法,把每个算法封装成独立的类,使它们可以互相替换,从而消除业务代码中的if-else。比如通知服务需要支持短信、邮件、推送等多种方式,传统做法是在一个方法里用if-else判断类型,每新增一种方式就要改代码,违反开闭原则。用策略模式重构分三步:第一步定义策略接口比如NotifyStrategy;第二步每种通知方式实现一个策略类,用@Component注解注册到Spring容器;第三步用Map做路由分发,Spring可以自动把所有实现类注入到Map<String, NotifyStrategy>中,key是beanName,调用时直接map.get(type).send()一行搞定。Java中经典的策略模式包括Comparator传给Collections.sort()、ThreadPoolExecutor的四种拒绝策略等。策略模式和状态模式的区别在于:策略由客户端主动选择,状态由对象内部自动切换。

追问与易错

追问方向:

  • “策略模式怎么消除 if-else?”→ 用 Map<String, Strategy> 做路由分发,Spring 自动把所有实现类注入到 Map 中(key=beanName),调用时 map.get(type).execute() 一行搞定,新增策略只需加实现类
  • “策略模式和工厂模式结合怎么用?”→ 工厂负责根据类型创建/选择具体策略实例(封装选择逻辑),客户端只和工厂交互不直接依赖策略实现类,Spring 中 Map 注入本质就是自动化的策略工厂
  • “你项目中哪里用了策略模式?”→ 常见场景:多种支付方式选择、不同渠道的消息推送、多种文件导出格式(Excel/PDF/CSV)、不同业务类型的计费规则等,核心是有多种可互换的算法实现

易错点:

  • ❌ “每次新增策略都要改代码”——用 Spring 自动注入所有实现类到 Map 中
  • ❌ 混淆策略模式和状态模式——策略由客户端选择,状态由内部自动切换