设计模式之策略模式

策略模式(Strategy Pattern)全解析:Java 架构师从理论到企业级实战

在 Java 企业级开发、微服务架构、分布式系统、电商金融等核心领域,代码的可扩展性、可维护性、解耦性是架构设计的核心指标。设计模式作为软件工程的最佳实践,是解决这些问题的核心工具;而策略模式作为行为型设计模式的经典代表,是消除代码中臃肿的if-else/switch分支、实现算法灵活切换、完美契合设计模式七大原则的最优解

作为 Java 架构师,本文将从设计模式七大原则为基石,深度拆解策略模式的核心思想、结构、分层代码实现,结合SpringBoot 企业级实战真实业务场景主流框架源码应用,全面剖析策略模式的落地价值与核心优势,全文内容深度覆盖架构设计、编码实践、业务落地全维度,助力你彻底掌握策略模式的精髓。


前言:为什么我们需要策略模式?

在实际项目开发中,我们经常遇到同一行为存在多种实现算法的场景:

  • 电商结算:无优惠、满减、折扣、优惠券、秒杀等多种优惠算法;
  • 支付系统:微信支付、支付宝、银联、云闪付等多种支付渠道;
  • 文件处理:Excel、CSV、PDF、Word 等多种文件解析 / 导出算法;
  • 登录认证:密码、短信、OAuth2.0、人脸等多种登录验证算法。

传统开发中,我们通常用大量的条件判断语句实现这些逻辑,导致代码臃肿、耦合度高、难以扩展、难以测试。而策略模式的核心价值,就是将算法的定义与算法的使用彻底分离,让算法独立变化、灵活替换,最终让系统架构更优雅、更健壮。


第一部分:设计模式七大核心原则(策略模式的基石)

策略模式之所以成为经典设计模式,核心原因是它完美契合设计模式七大原则。在深入策略模式前,我们必须先吃透这七大原则,这是架构设计的底层逻辑。

原则名称 英文缩写 核心定义 设计核心
单一职责原则 SRP 一个类只负责一项职责,只有一个引起变化的原因 高内聚
开闭原则 OCP 软件实体对扩展开放,对修改关闭 可扩展
里氏替换原则 LSP 父类引用可无缝替换子类对象,子类不破坏父类契约 继承规范
依赖倒置原则 DIP 面向抽象编程,高层依赖抽象,细节依赖抽象 解耦
接口隔离原则 ISP 客户端不依赖不需要的接口,接口精简单一 接口精简
迪米特法则 LOD 一个对象只与直接朋友通信,最少知道原则 低耦合
合成复用原则 CRP 优先使用对象组合 / 聚合,而非继承实现复用 弱耦合

1. 单一职责原则(SRP)

一个类如果承担多个职责,任意一个职责的变更都会影响其他功能,导致代码难以维护。最优实践:一个类只做一件事

反例:一个类同时处理支付、退款、提现;

正例:拆分支付策略、退款策略、提现策略,各司其职。

2. 开闭原则(OCP)

软件设计的终极原则:新增功能时,通过扩展代码实现,绝不修改原有核心业务代码,避免修改引发的线上 bug。

反例:新增支付方式时,直接修改原有if-else支付逻辑;

正例:新增支付策略实现类,不改动任何原有代码。

3. 里氏替换原则(LSP)

继承 / 实现必须遵循契约:所有使用父类 / 接口的地方,都可以无缝替换子类 / 实现类对象,子类不能重写父类核心业务方法。

反例:支付实现类随意修改接口契约,导致调用异常;

正例:所有支付策略严格实现支付接口,接口引用可替换任意实现。

4. 依赖倒置原则(DIP)

架构设计的核心解耦原则:高层模块不依赖低层模块,二者都依赖抽象;抽象不依赖细节,细节依赖抽象

反例:业务 Service 直接依赖AlipayServiceImpl具体实现类;

正例:业务 Service 依赖PayStrategy抽象接口,面向接口编程。

5. 接口隔离原则(ISP)

避免臃肿接口,将大接口拆分为多个小接口,客户端只依赖自己需要的接口。

反例:一个支付接口包含支付、退款、提现、查询所有方法;

正例:拆分PayStrategyRefundStrategyWithdrawStrategy独立接口。

6. 迪米特法则(LOD)

最少知道原则:一个对象对其他对象的了解越少越好,只与直接依赖的对象通信。

反例:客户端直接创建所有支付策略对象,耦合所有实现类;

正例:客户端只与上下文类交互,屏蔽具体策略细节。

7. 合成复用原则(CRP)

继承是强耦合,组合是弱耦合:优先使用对象组合 / 聚合实现复用,而非继承。

反例:通过多层继承实现不同优惠逻辑,继承层级混乱;

正例:上下文类通过组合持有策略对象,动态切换算法。


第二部分:策略模式核心基础认知

1. 策略模式官方定义(GoF)

策略模式定义了一系列的算法,将每一个算法封装到独立的类中,并且使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端

2. 策略模式核心角色(4 大核心组件)

策略模式是典型的分层设计,将算法定义、算法实现、算法调用、客户端使用彻底分离,四大角色分工明确:

角色名称 类型 核心职责 代码表现
抽象策略(Strategy) 接口 / 抽象类 定义所有算法的公共契约(方法) PayStrategyPromotionStrategy
具体策略(ConcreteStrategy) 实现类 实现抽象策略接口,提供具体算法逻辑 AlipayStrategyFullReductionStrategy
上下文(Context) 业务调度类 持有策略对象引用,对外提供统一调用入口,屏蔽客户端直接访问策略 PayContextPromotionContext
客户端(Client) 调用方 创建策略对象,传递给上下文,触发算法执行 Controller/Test 类

3. 策略模式 UML 类图(文字描述)

  1. Context组合持有 Strategy 接口对象;
  2. Context 提供 setStrategy() 动态切换策略、execute() 调用算法;
  3. ConcreteStrategyA/B/C 实现 Strategy 接口,重写核心算法方法;
  4. 客户端仅与 Context 交互,无需关注具体策略实现。

4. 策略模式核心思想

分离算法定义与算法使用,封装可变算法,开放灵活扩展

  • 可变部分:具体算法实现(封装到策略类);
  • 不变部分:算法调用逻辑(封装到上下文);
  • 客户端:无感使用算法,无需关心实现细节。

第三部分:反例:传统实现方式的致命痛点

我们以电商商品优惠结算为场景,先看传统if-else实现,直观感受代码的缺陷:

需求

商品原价结算,支持 4 种优惠:无优惠、满 100 减 20、8 折优惠、优惠券减 30。

传统硬编码实现

import java.math.BigDecimal;

/**
 * 传统优惠服务:违反所有设计原则
 */
public class TraditionalPromotionService {

    /**
     * 计算优惠后价格(全是if-else,臃肿到极致)
     * @param originalPrice 原价
     * @param type 优惠类型:NONE/FULL_REDUCTION/DISCOUNT/COUPON
     * @return 优惠后价格
     */
    public BigDecimal calculatePrice(BigDecimal originalPrice, String type) {
        // 1. 无优惠
        if ("NONE".equals(type)) {
            return originalPrice;
        }
        // 2. 满减优惠
        else if ("FULL_REDUCTION".equals(type)) {
            if (originalPrice.compareTo(new BigDecimal("100")) >= 0) {
                return originalPrice.subtract(new BigDecimal("20"));
            }
            return originalPrice;
        }
        // 3. 折扣优惠
        else if ("DISCOUNT".equals(type)) {
            return originalPrice.multiply(new BigDecimal("0.8"));
        }
        // 4. 优惠券优惠
        else if ("COUPON".equals(type)) {
            return originalPrice.subtract(new BigDecimal("30"));
        }
        // 非法类型
        else {
            throw new IllegalArgumentException("不支持的优惠类型:" + type);
        }
    }
}

传统写法的致命缺陷(架构师必避坑)

  1. 违反单一职责:一个类承载所有优惠算法,职责混乱;
  2. 违反开闭原则:新增秒杀优惠,必须修改if-else代码,风险极高;
  3. 代码臃肿:分支过多,可读性极差,后期难以维护;
  4. 违反迪米特法则:客户端必须记住所有优惠类型字符串,强耦合;
  5. 违反合成复用:无任何代码复用,全是硬编码;
  6. 难以测试:一个方法包含所有逻辑,单元测试覆盖率极低;
  7. 协作成本高:多人开发时,极易出现代码冲突。

这就是企业级项目中必须用策略模式的核心原因:传统写法完全不符合架构设计规范,无法支撑业务快速迭代。


第四部分:策略模式 Java 代码实现(三层进阶:基础→优化→企业级)

我们以电商优惠结算为场景,分三个阶段实现策略模式,从基础版到 SpringBoot 企业级实战版,逐步优化,贴合真实项目开发。

阶段 1:基础标准版策略模式(核心原理)

严格遵循策略模式四大角色,实现最纯粹的策略模式。

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

定义优惠算法的公共契约,遵循接口隔离原则

import java.math.BigDecimal;

/**
 * 抽象优惠策略:定义所有优惠的统一接口
 */
public interface PromotionStrategy {
    /**
     * 计算优惠后价格
     * @param originalPrice 商品原价
     * @return 优惠后价格
     */
    BigDecimal calculateDiscountPrice(BigDecimal originalPrice);
}

步骤 2:定义具体策略类(ConcreteStrategy)

每个策略类只实现一种算法,遵循单一职责原则

// 1. 无优惠策略
public class NonePromotion implements PromotionStrategy {
    @Override
    public BigDecimal calculateDiscountPrice(BigDecimal originalPrice) {
        return originalPrice;
    }
}

// 2. 满减策略:满100减20
public class FullReductionPromotion implements PromotionStrategy {
    @Override
    public BigDecimal calculateDiscountPrice(BigDecimal originalPrice) {
        if (originalPrice.compareTo(new BigDecimal("100")) >= 0) {
            return originalPrice.subtract(new BigDecimal("20"));
        }
        return originalPrice;
    }
}

// 3. 折扣策略:8折
public class DiscountPromotion implements PromotionStrategy {
    @Override
    public BigDecimal calculateDiscountPrice(BigDecimal originalPrice) {
        return originalPrice.multiply(new BigDecimal("0.8"));
    }
}

// 4. 优惠券策略:减30
public class CouponPromotion implements PromotionStrategy {
    @Override
    public BigDecimal calculateDiscountPrice(BigDecimal originalPrice) {
        return originalPrice.subtract(new BigDecimal("30"));
    }
}

步骤 3:定义上下文类(Context)

持有策略对象,对外提供统一调用入口,屏蔽客户端直接访问策略,遵循迪米特法则+合成复用原则

import java.math.BigDecimal;

/**
 * 优惠上下文:负责调度优惠策略
 */
public class PromotionContext {
    // 组合持有抽象策略对象(合成复用原则)
    private final PromotionStrategy promotionStrategy;

    // 构造器注入策略
    public PromotionContext(PromotionStrategy promotionStrategy) {
        this.promotionStrategy = promotionStrategy;
    }

    // 对外统一调用入口
    public BigDecimal executeCalculate(BigDecimal originalPrice) {
        return promotionStrategy.calculateDiscountPrice(originalPrice);
    }
}

步骤 4:客户端调用(Client)

面向接口编程,遵循依赖倒置原则

import java.math.BigDecimal;

public class Client {
    public static void main(String[] args) {
        BigDecimal originalPrice = new BigDecimal("200");

        // 1. 使用无优惠策略
        PromotionContext context1 = new PromotionContext(new NonePromotion());
        System.out.println("无优惠:" + context1.executeCalculate(originalPrice));

        // 2. 使用满减策略
        PromotionContext context2 = new PromotionContext(new FullReductionPromotion());
        System.out.println("满减优惠:" + context2.executeCalculate(originalPrice));

        // 3. 动态切换折扣策略
        PromotionContext context3 = new PromotionContext(new DiscountPromotion());
        System.out.println("折扣优惠:" + context3.executeCalculate(originalPrice));
    }
}

基础版总结

  • 彻底分离算法定义与使用;
  • 每个策略类职责单一;
  • 客户端面向接口编程,解耦具体实现。

阶段 2:优化版:工厂模式 + 策略模式(消除客户端判断)

基础版的缺陷:客户端需要手动创建策略对象,仍存在简单的判断逻辑。

优化方案:结合简单工厂模式,将策略对象的创建封装到工厂中,客户端只需传入类型,工厂自动返回对应策略。

新增:策略工厂类

/**
 * 优惠策略工厂:封装策略对象创建
 */
public class PromotionStrategyFactory {
    // 私有化构造器,禁止实例化
    private PromotionStrategyFactory() {}

    /**
     * 根据类型获取优惠策略
     */
    public static PromotionStrategy getStrategy(String type) {
        return switch (type) {
            case "NONE" -> new NonePromotion();
            case "FULL_REDUCTION" -> new FullReductionPromotion();
            case "DISCOUNT" -> new DiscountPromotion();
            case "COUPON" -> new CouponPromotion();
            default -> throw new IllegalArgumentException("不支持的优惠类型");
        };
    }
}

优化后客户端调用

public class Client {
    public static void main(String[] args) {
        BigDecimal originalPrice = new BigDecimal("200");
        // 客户端只需传入类型,无需创建策略对象
        PromotionContext context = new PromotionContext(PromotionStrategyFactory.getStrategy("FULL_REDUCTION"));
        System.out.println("工厂+策略模式:满减优惠 = " + context.executeCalculate(originalPrice));
    }
}

优化版优势

  • 消除客户端的策略创建逻辑;
  • 集中管理所有策略,便于维护;
  • 进一步降低客户端与策略的耦合。

阶段 3:企业级版:SpringBoot 整合策略模式(真实项目落地)

在微服务项目中,我们不会手动创建对象,而是通过Spring IOC 容器管理 Bean,结合自定义注解实现策略的自动注册与发现,这是互联网公司最常用的落地方式。

步骤 1:SpringBoot 项目依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

步骤 2:自定义策略类型注解

标识策略类对应的业务类型,实现自动绑定。

import java.lang.annotation.*;

/**
 * 自定义优惠策略注解:标识策略类型
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // 交给Spring管理
public @interface PromotionType {
    /**
     * 优惠类型:NONE/FULL_REDUCTION/DISCOUNT/COUPON
     */
    String value();
}

步骤 3:改造具体策略类(添加注解)

// 无优惠策略
@PromotionType("NONE")
public class NonePromotion implements PromotionStrategy {
    @Override
    public BigDecimal calculateDiscountPrice(BigDecimal originalPrice) {
        return originalPrice;
    }
}

// 满减策略
@PromotionType("FULL_REDUCTION")
public class FullReductionPromotion implements PromotionStrategy {
    @Override
    public BigDecimal calculateDiscountPrice(BigDecimal originalPrice) {
        if (originalPrice.compareTo(new BigDecimal("100")) >= 0) {
            return originalPrice.subtract(new BigDecimal("20"));
        }
        return originalPrice;
    }
}

// 折扣策略、优惠券策略同理添加注解

步骤 4:Spring 策略工厂(自动加载所有策略)

通过 Spring 上下文获取所有标注@PromotionType的 Bean,自动注册到 Map 中。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class SpringPromotionStrategyFactory {
    @Autowired
    private ApplicationContext applicationContext;

    // 存储所有策略:key=优惠类型,value=策略对象
    private static final Map<String, PromotionStrategy> STRATEGY_MAP = new ConcurrentHashMap<>();

    /**
     * 项目启动时,自动加载所有优惠策略
     */
    @PostConstruct
    public void initStrategies() {
        // 获取所有标注@PromotionType的Bean
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(PromotionType.class);
        for (Object bean : beans.values()) {
            if (!(bean instanceof PromotionStrategy)) continue;
            // 获取注解中的类型
            PromotionType annotation = bean.getClass().getAnnotation(PromotionType.class);
            String type = annotation.value();
            // 存入Map
            STRATEGY_MAP.put(type, (PromotionStrategy) bean);
        }
    }

    /**
     * 获取策略
     */
    public PromotionStrategy getStrategy(String type) {
        PromotionStrategy strategy = STRATEGY_MAP.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的优惠类型:" + type);
        }
        return strategy;
    }
}

步骤 5:上下文类(交给 Spring 管理)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;

@Component
public class PromotionContext {
    @Autowired
    private SpringPromotionStrategyFactory strategyFactory;

    // 动态计算优惠价格
    public BigDecimal calculatePrice(BigDecimal originalPrice, String type) {
        PromotionStrategy strategy = strategyFactory.getStrategy(type);
        return strategy.calculateDiscountPrice(originalPrice);
    }
}

步骤 6:Controller 接口(对外提供服务)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;

@RestController
public class PromotionController {
    @Autowired
    private PromotionContext promotionContext;

    @GetMapping("/calculate")
    public String calculate(@RequestParam BigDecimal price, @RequestParam String type) {
        BigDecimal result = promotionContext.calculatePrice(price, type);
        return "原价:" + price + ",优惠后价格:" + result;
    }
}

企业级版核心优势

  1. 完全基于 Spring IOC 管理,无手动创建对象;
  2. 新增策略零代码修改:只需新增策略类 + 添加@PromotionType注解;
  3. 自动注册策略,无需维护工厂代码;
  4. 适配微服务、分布式系统,生产环境直接可用。

第五部分:策略模式与七大设计原则深度结合(架构核心)

这是策略模式成为架构师首选模式的核心原因:它完美满足所有七大设计原则,我们结合上面的代码逐一验证:

1. 契合单一职责原则(SRP)

  • 每个具体策略类(如FullReductionPromotion只实现一种优惠算法,职责单一;
  • 上下文类PromotionContext只负责策略调度,不实现任何算法;
  • 策略工厂只负责策略创建,分工明确,高内聚。

2. 契合开闭原则(OCP)

  • 扩展开放:新增秒杀优惠,只需创建SeckillPromotion类 + 添加@PromotionType("SECKILL")注解;
  • 修改关闭:原有接口、上下文、工厂、业务代码完全不改动
  • 彻底避免修改原有代码带来的 bug 风险。

3. 契合里氏替换原则(LSP)

  • 所有策略类都实现PromotionStrategy接口,严格遵循接口契约
  • 客户端使用接口引用,可无缝替换任意策略实现类,无任何异常;
  • 子类不破坏父类契约,符合继承 / 实现规范。

4. 契合依赖倒置原则(DIP)

  • 高层模块(Controller、Context)依赖抽象接口PromotionStrategy,不依赖具体策略类;
  • 低层策略类依赖抽象接口实现自己的逻辑;
  • 彻底实现面向接口编程,解耦高层与低层。

5. 契合接口隔离原则(ISP)

  • 抽象策略接口只定义一个核心方法calculateDiscountPrice,无任何冗余方法;
  • 实现类只需实现必要方法,无需实现无用接口;
  • 接口精简单一,符合最小接口原则。

6. 契合迪米特法则(LOD)

  • 客户端(Controller)只与上下文类交互,完全不知道具体策略的存在;
  • 策略的创建、调度、执行全部封装在内部,客户端无感知;
  • 类之间耦合度极低,最少知道。

7. 契合合成复用原则(CRP)

  • 上下文类通过组合持有策略接口对象,而非继承策略类;
  • 组合是弱耦合,可动态切换策略;
  • 避免继承带来的强耦合、层级混乱问题。

第六部分:策略模式在企业级项目中的实战应用场景(全覆盖)

策略模式是业务多变场景的万能解,在 Java 企业级开发中应用无处不在,以下是 11 个高频实战场景,每个场景都贴合真实业务:

场景 1:电商支付渠道策略(最经典)

业务需求

支持微信支付、支付宝、银联、云闪付、数字人民币多种支付方式,用户可自由切换。

策略模式落地

  • 抽象策略:PayStrategy(支付、退款接口);
  • 具体策略:WechatPayStrategyAlipayStrategyUnionPayStrategy
  • 上下文:PayContext
  • 扩展:新增支付方式,只需加策略类,无代码改动。

场景 2:电商营销促销策略

业务需求

满减、折扣、优惠券、秒杀、拼团、预售、会员价等 10 + 种优惠方式。

策略模式落地

本文实战案例,完美适配,支持营销活动快速上线。

场景 3:文件解析 / 导出策略

业务需求

解析 Excel、CSV、PDF、Word 文件;导出 Excel、CSV、PDF 格式报表。

策略模式落地

  • 抽象策略:FileParseStrategyFileExportStrategy
  • 具体策略:ExcelParseStrategyPdfExportStrategy
  • 优势:新增文件格式,零改动扩展。

场景 4:用户登录认证策略

业务需求

密码登录、短信验证码、微信 OAuth2.0、支付宝登录、人脸登录。

策略模式落地

  • 抽象策略:LoginStrategy
  • 具体策略:PasswordLoginStrategySmsLoginStrategy
  • 适配多端登录,灵活切换认证方式。

场景 5:分布式缓存策略

业务需求

本地缓存(Caffeine)、Redis 缓存、Memcached 缓存动态切换。

策略模式落地

  • 抽象策略:CacheStrategy
  • 具体策略:LocalCacheStrategyRedisCacheStrategy
  • 适配不同业务场景的缓存需求。

场景 6:数据加密解密策略

业务需求

AES 对称加密、RSA 非对称加密、MD5/SHA 摘要加密、国密 SM4。

策略模式落地

  • 抽象策略:EncryptStrategy
  • 具体策略:AesEncryptStrategyRsaEncryptStrategy
  • 金融、支付系统必备。

场景 7:JDK 原生线程池拒绝策略

业务需求

线程池满时,4 种拒绝策略:

  1. AbortPolicy:抛出异常(默认);
  2. CallerRunsPolicy:调用者线程执行;
  3. DiscardPolicy:丢弃任务;
  4. DiscardOldestPolicy:丢弃最老任务。

策略模式落地

JDK 线程池直接使用策略模式,RejectedExecutionHandler是抽象策略,4 个实现类是具体策略。

场景 8:消息推送策略

业务需求

短信推送、APP 推送、微信公众号推送、邮件推送、钉钉推送。

策略模式落地

  • 抽象策略:PushStrategy
  • 具体策略:SmsPushStrategyEmailPushStrategy
  • 灵活切换推送渠道。

场景 9:支付风控策略

业务需求

低风险直接通过、中风险短信验证、高风险拦截订单。

策略模式落地

  • 抽象策略:RiskControlStrategy
  • 具体策略:LowRiskStrategyHighRiskStrategy
  • 金融支付核心场景。

场景 10:数据排序 / 筛选策略

业务需求

商品按价格、销量、评分、创建时间排序。

策略模式落地

JDK Comparator接口就是策略模式,Collections.sort(list, comparator)动态切换排序规则。

场景 11:报表生成策略

业务需求

销售报表、库存报表、用户报表、财务报表,不同报表生成逻辑不同。

策略模式落地

  • 抽象策略:ReportStrategy
  • 具体策略:SalesReportStrategyStockReportStrategy
  • 企业后台管理系统必备。

第七部分:策略模式带来的核心优势(架构师必知)

策略模式是企业级开发的刚需设计模式,相比传统if-else写法,拥有 10 大核心优势:

1. 彻底解耦:算法定义与算法使用分离

策略模式将可变的算法不变的调用逻辑彻底分离,算法的修改不影响调用方,调用方的变更不影响算法实现,符合关注点分离架构思想。

2. 极致扩展:完美遵循开闭原则

新增算法零修改原有代码,只需新增策略实现类,完全适配业务快速迭代,是微服务、电商、金融等多变业务的最佳选择。

3. 消除冗余:告别臃肿的 if-else/switch

传统业务中,百行级别的条件判断是常态,策略模式将分支拆分为独立类,代码简洁到极致,可读性提升 10 倍。

4. 高可维护性:职责单一,代码清晰

每个策略类只做一件事,代码量极少,后期维护、排查 bug、修改逻辑都极其简单,降低运维成本。

5. 灵活替换:运行时动态切换算法

通过上下文的setStrategy方法,可在运行时动态切换算法,无需重启服务,适配实时业务需求。

6. 高可测试性:单元测试极简

每个策略类独立存在,可单独编写单元测试,测试覆盖率 100%,避免传统写法整体测试的复杂性。

7. 规范架构:强制遵循七大设计原则

策略模式从设计层面约束开发者写出高质量代码,避免烂代码,提升团队整体架构水平。

8. 低耦合:客户端无感知算法细节

客户端只与上下文交互,无需知道具体算法实现,符合迪米特法则,系统耦合度极低。

9. 高效协作:多人开发无冲突

不同开发者负责不同策略类,代码完全隔离,无合并冲突,提升团队开发效率。

10. 生产级可用:主流框架原生支持

Spring、SpringBoot、JDK、MyBatis 等主流框架原生使用策略模式,与生态完美融合,生产环境稳定可靠。


第八部分:策略模式注意事项与优化方案

1. 策略类膨胀问题

当算法过多时,会产生大量策略类(类爆炸)。

优化方案

  • 结合枚举 + 策略合并简单策略;
  • 抽象策略类抽取公共代码,减少重复;
  • Spring 自动注册策略,集中管理。

2. 避免过度设计

  • 简单固定算法(无扩展需求):无需使用策略模式;
  • 只有 1-2 种算法:直接硬编码即可,防止过度设计增加复杂度。

3. 公共代码抽取

将所有策略的公共逻辑抽取到抽象策略类中,具体策略继承抽象类,减少重复代码。

4. 策略选择逻辑集中

策略的选择逻辑统一放在工厂 / 上下文中,绝不分散在客户端,便于维护。


第九部分:策略模式在主流框架源码中的应用

策略模式是框架设计的标配,以下是 Java 生态中最经典的应用:

1. JDK Comparator 接口

java.util.Comparator是抽象策略,自定义比较器是具体策略,Collections.sort(List, Comparator)是上下文调用。

2. JDK 线程池拒绝策略

RejectedExecutionHandler(抽象策略) + 4 个实现类(具体策略) + ThreadPoolExecutor(上下文)。

3. Spring BeanNameGenerator

Bean 名称生成策略,支持默认生成、自定义生成,完美使用策略模式。

4. Spring MVC HandlerMapping

请求映射策略,RequestMappingHandlerMappingBeanNameUrlHandlerMapping是具体策略。

5. MyBatis 日志模块

Log接口(抽象策略),适配 SLF4J、Log4j、Console 等日志框架(具体策略)。


第十部分:策略模式与相似设计模式的区分

1. 策略模式 VS 模板方法模式

  • 策略模式:组合 / 委托,算法完全独立,无固定流程;
  • 模板方法:继承,固定算法流程,仅开放部分步骤自定义。

2. 策略模式 VS 状态模式

  • 策略模式:算法切换无状态依赖,由客户端主动指定;
  • 状态模式:行为切换由状态自动触发,有状态依赖。

3. 策略模式 VS 适配器模式

  • 策略模式:替换算法,功能相同,实现不同;
  • 适配器模式:兼容接口,功能不同,适配调用。

总结

策略模式是 Java 架构师必须掌握的核心行为型设计模式,它以七大设计原则为基石,彻底解决了算法多变、代码臃肿、耦合度高的行业痛点。

本文从基础理论→代码实现→企业级 SpringBoot 实战→业务场景→框架源码全维度拆解策略模式,核心价值总结:

  1. 核心思想:分离算法定义与使用,封装可变,开放扩展;
  2. 设计合规:完美契合七大设计原则,是架构设计的标杆;
  3. 业务价值:消除 if-else,支持灵活扩展,适配所有多变业务场景;
  4. 生产落地:SpringBoot 整合方案可直接用于微服务、电商、金融等生产项目。

在实际开发中,只要遇到同一行为多种实现的场景,优先选择策略模式,它能让你的代码从「臃肿混乱」变为「优雅可扩展」,是架构师提升代码质量的核心武器。

posted @ 2026-04-09 19:56  bright_ye  阅读(20)  评论(0)    收藏  举报