Java策略模式从入门到实战:小白也能看懂的设计模式指南

🌟 一句话理解策略模式:把“怎么做”抽出来,让程序能灵活换算法,而不改代码!


① 技术栈用途介绍:它到底能解决什么问题?

想象你开了一家「智能优惠券系统」——用户下单时,要根据会员等级(普通/黄金/VIP)自动应用不同折扣规则:

  • 普通用户:95折
  • 黄金用户:9折
  • VIP用户:满300减50

如果不用策略模式,你可能写出这样的“硬编码”逻辑:

if (userLevel.equals("normal")) {
    price = price * 0.95;
} else if (userLevel.equals("gold")) {
    price = price * 0.9;
} else if (userLevel.equals("vip")) {
    price = Math.max(0, price - 50);
}
// ❌ 新增SVIP?还得加else if!改代码、测全量、上线风险高!

策略模式就是为了解决这种“条件分支爆炸”和“业务规则频繁变更”的痛点

  • ✅ 将每种折扣规则封装成独立的「策略类」
  • ✅ 运行时动态选择,新增规则只需加个类 + 注册,零修改原有逻辑!
  • ✅ 符合开闭原则(对扩展开放,对修改关闭)

💡 典型场景:支付方式选择(微信/支付宝/银联)、日志输出策略(控制台/文件/远程)、促销计算、排序算法切换、风控规则引擎等。


② 环境准备与安装配置:5分钟配好开发环境

无需额外安装!策略模式是纯Java语言级设计模式,JDK 8+ 即可直接使用。

你只需要

  • JDK 1.8 或更高版本(推荐 JDK 17)
  • IDE:IntelliJ IDEA(社区版免费)或 VS Code + Java Extension Pack
  • 构建工具:Maven(IDE通常自带)

🔧 检查JDK是否就绪(终端执行)

java -version
mvn -v

⚠️ 新手常见坑 & 排查: | 问题 | 原因 | 解决 | |------|------|------| | Cannot resolve symbol 'Strategy' | 没定义接口/类名拼错 | 确保接口名为 DiscountStrategy,类实现 implements DiscountStrategy | | 运行报 NullPointerException | 策略对象未初始化 | 检查 Context 中是否调用 setStrategy(...) 或构造传入 | | Maven依赖报红 | 项目未识别为Maven工程 | 右键项目 → Add Framework Support → 选 Maven |


③ 入门实践:10分钟跑通第一个策略Demo

我们用「优惠券系统」写一个最小可运行示例(完整可复制):

Step 1:定义策略接口

// src/main/java/com/example/strategy/DiscountStrategy.java
public interface DiscountStrategy {
    double calculate(double originalPrice);
}

Step 2:实现3个具体策略

// 普通用户策略
public class NormalDiscount implements DiscountStrategy {
    @Override
    public double calculate(double originalPrice) {
        return originalPrice * 0.95;
    }
}

// 黄金用户策略
public class GoldDiscount implements DiscountStrategy {
    @Override
    public double calculate(double originalPrice) {
        return originalPrice * 0.9;
    }
}

// VIP用户策略
public class VipDiscount implements DiscountStrategy {
    @Override
    public double calculate(double originalPrice) {
        return Math.max(0, originalPrice - 50);
    }
}

Step 3:创建上下文(策略的“调度员”)

// src/main/java/com/example/strategy/DiscountContext.java
public class DiscountContext {
    private DiscountStrategy strategy;

    // 支持运行时切换策略
    public void setStrategy(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    public double applyDiscount(double price) {
        if (strategy == null) {
            throw new IllegalStateException("策略未设置!");
        }
        return strategy.calculate(price);
    }
}

Step 4:编写主程序测试

// src/main/java/com/example/strategy/Main.java
public class Main {
    public static void main(String[] args) {
        DiscountContext context = new DiscountContext();

        // 模拟不同用户下单
        context.setStrategy(new NormalDiscount());
        System.out.println("普通用户下单:¥100 → ¥" + context.applyDiscount(100)); // 95.0

        context.setStrategy(new GoldDiscount());
        System.out.println("黄金用户下单:¥100 → ¥" + context.applyDiscount(100)); // 90.0

        context.setStrategy(new VipDiscount());
        System.out.println("VIP用户下单:¥100 → ¥" + context.applyDiscount(100)); // 50.0
        System.out.println("VIP用户下单:¥400 → ¥" + context.applyDiscount(400)); // 350.0
    }
}

运行结果

普通用户下单:¥100 → ¥95.0
黄金用户下单:¥100 → ¥90.0
VIP用户下单:¥100 → ¥50.0
VIP用户下单:¥400 → ¥350.0

🎉 恭喜!你已成功实现策略模式 —— 所有折扣逻辑解耦,新增SVIP只需加个 SvipDiscount 类,一行代码都不用改!


④ 进阶与原理:不只是“换个类”,更要懂它怎么工作

🔍 核心机制图解

          ┌──────────────────┐
          │   DiscountContext│ ← 用户只和它打交道
          │  (持有策略引用)   │
          └────────┬─────────┘
                   │ 调用
     ┌────────────▼─────────────┐   ┌────────────▼─────────────┐
     │   NormalDiscount         │   │      GoldDiscount        │
     │  implements Strategy     │   │  implements Strategy     │
     └──────────────────────────┘   └──────────────────────────┘
                ▲                            ▲
                └────────────────────────────┘
                         ↑ 实现同一接口

✨ 高级技巧 & 最佳实践

  • 策略工厂 + Spring整合(推荐生产用)

    @Service
    public class DiscountStrategyFactory {
        private final Map<String, DiscountStrategy> strategies;
    
        public DiscountStrategyFactory(
                NormalDiscount normal,
                GoldDiscount gold,
                VipDiscount vip) {
            this.strategies = Map.of(
                "normal", normal,
                "gold", gold,
                "vip", vip
            );
        }
    
        public DiscountStrategy get(String type) {
            return strategies.getOrDefault(type, new NormalDiscount());
        }
    }
    

    使用时:context.setStrategy(factory.get(user.getLevel()));

  • 策略+枚举统一管理(避免字符串硬编码):

    public enum DiscountType {
        NORMAL(new NormalDiscount()),
        GOLD(new GoldDiscount()),
        VIP(new VipDiscount());
    
        private final DiscountStrategy strategy;
        DiscountType(DiscountStrategy s) { this.strategy = s; }
        public DiscountStrategy get() { return strategy; }
    }
    // 调用:context.setStrategy(DiscountType.VIP.get());
    
  • 为什么不用if-else?性能对比

    • if-else:编译期确定,CPU分支预测友好,但维护成本指数级增长
    • 策略模式:运行期多态(虚方法调用),性能损耗≈0.1%,换来的是无限可扩展性与单元测试友好性(每个策略可单独Mock测试)

⑤ 总结与评估:它适合你吗?

| 维度 | 说明 | |------------|------| | ✅ 核心优点 | • 高内聚低耦合,业务规则彻底解耦
• 新增/替换策略零侵入主流程
• 易于单元测试(每个策略独立验证)
• 天然支持Spring Bean动态注入 | | ⚠️ 局限性 | • 策略过多时需配合工厂/枚举管理,否则易混乱
• 简单场景(仅2种策略)反而增加复杂度(YAGNI原则) | | 🆚 vs 状态模式 | 状态模式关注「对象内部状态变化导致行为改变」(如订单:待支付→已支付→已发货);策略模式关注「外部算法切换」,策略间无状态流转关系。 | | 🎯 适用场景 | • 同一问题有多种算法实现(如排序、压缩、加密)
• 业务规则频繁变更(营销、风控、计费)
• 需要运行时动态决策(如A/B测试分流) | | 📚 后续学习建议 | ① 学习「模板方法模式」(父类定骨架,子类填细节)
② 对比「责任链模式」(多个处理器串行处理请求)
③ 实战:用策略模式重构你项目中的 if-else 集中式判断块! |


💡 最后送你一句口诀

“一接口、多实现、上下文来调度;新算法、加个类、老代码不用改!”

现在,打开你的IDE,亲手敲一遍Demo吧!遇到问题欢迎在评论区留言 👇 我会一一解答~

#Java #设计模式 #策略模式 #编程入门 #CSDN教程

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐