Java设计模式漫画英雄宇宙之策略模式:从支付系统重构到软考高频考点(附完整代码 + 面试高频问法)

🎭 一、漫画开场:小贾的"支付之痛"

小贾是一个刚接手电商系统的新晋 Java 工程师。某天,产品经理跑来:"咱们要支持微信、支付宝、银联、京东支付、Apple Pay,而且未来可能还要加数字货币!"

他翻开支付模块,看到这样的代码:

java 复制代码
public void pay(String payType, double amount) {
    if ("wechat".equals(payType)) {
        // 微信支付逻辑
    } else if ("alipay".equals(payType)) {
        // 支付宝逻辑
    } else if ("unionpay".equals(payType)) {
        // 银联逻辑
    } 
    // ......未来还要加更多 if-else
}public void pay(String payType, double amount) {
    if ("wechat".equals(payType)) {
        // 微信支付逻辑
    } else if ("alipay".equals(payType)) {
        // 支付宝逻辑
    } else if ("unionpay".equals(payType)) {
        // 银联逻辑
    } 
    // ......未来还要加更多 if-else
}

"这哪是代码,这是技术债炸弹!"小贾哀嚎。

这时,神秘高人策略大师·阿策 闪现:"年轻人,你需要------策略模式(Strategy Pattern)!"

🔍 二、策略模式:定义与核心思想

GoF 定义

定义一系列算法,将每一个算法封装起来,并使它们可以互相替换。策略模式让算法的变化独立于使用它的客户端。
核心思想
将"变"与"不变"分离

  • 不变:支付流程(下单 → 选择方式 → 调用支付 → 返回结果)
  • 变:具体支付实现(微信、支付宝等)
    属于行为型设计模式 ,软考高级架构师考试中属于高频考点(尤其在"系统设计"和"代码重构"题型中)。

🏗️ 三、策略模式的三大角色(UML + 代码实现)

1. UML 类图(建议保存)

2. 完整 Java 代码实现(可直接复制运行)

java 复制代码
// 1. 策略接口:支付行为抽象
public interface PaymentStrategy {
    void pay(double amount);
}

// 2. 具体策略实现
public class WeChatPay implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("[微信支付] 扫码完成,支付金额:" + amount + " 元");
    }
}

public class Alipay implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("[支付宝] 指纹验证通过,支付金额:" + amount + " 元");
    }
}

public class UnionPay implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("[银联支付] 刷卡成功,支付金额:" + amount + " 元");
    }
}

// 3. 上下文:持有策略并执行
public class PaymentContext {
    private PaymentStrategy strategy;

    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void executePayment(double amount) {
        if (strategy == null) {
            throw new IllegalStateException("未设置支付策略!");
        }
        strategy.pay(amount);
    }
}

3. 客户端调用示例

java 复制代码
public class Main {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext();

        // 用户选择微信支付
        context.setPaymentStrategy(new WeChatPay());
        context.executePayment(99.9);

        // 用户切换为支付宝
        context.setPaymentStrategy(new Alipay());
        context.executePayment(199.0);
    }
}

✅ 输出:

微信支付 扫码完成,支付金额:99.9 元

支付宝 指纹验证通过,支付金额:199.0 元

🚀 四、进阶实战:策略 + 工厂 + 注解,打造企业级支付引擎

实际项目中,我们不会手动 new WeChatPay(),而是用策略工厂 + 注解自动注册,提升扩展性。

1. 定义支付类型枚举

java 复制代码
public enum PayType {
    WECHAT, ALIPAY, UNIONPAY
}

2. 添加策略标识注解

java 复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface PayStrategy {
    PayType value();
}

3. 策略类加上注解

java 复制代码
@PayStrategy(PayType.WECHAT)
public class WeChatPay implements PaymentStrategy { ... }

@PayStrategy(PayType.ALIPAY)
public class Alipay implements PaymentStrategy { ... }

4. 策略工厂(Spring 环境下可用 ApplicationContext 获取 Bean)

java 复制代码
@Component
public class PaymentStrategyFactory {

    private final Map<PayType, PaymentStrategy> strategyMap = new ConcurrentHashMap<>();

    // Spring 启动时自动注入所有策略
    public PaymentStrategyFactory(List<PaymentStrategy> strategies) {
        for (PaymentStrategy strategy : strategies) {
            PayStrategy annotation = strategy.getClass().getAnnotation(PayStrategy.class);
            if (annotation != null) {
                strategyMap.put(annotation.value(), strategy);
            }
        }
    }

    public PaymentStrategy getStrategy(PayType type) {
        PaymentStrategy strategy = strategyMap.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的支付方式: " + type);
        }
        return strategy;
    }
}

5. 服务层调用

java 复制代码
@Service
public class OrderService {

    @Autowired
    private PaymentStrategyFactory factory;

    public void pay(PayType type, double amount) {
        PaymentStrategy strategy = factory.getStrategy(type);
        strategy.pay(amount);
    }
}

✅ 优势:

  • 新增支付方式?只需写一个带注解的类,零修改
  • 符合 开闭原则(OCP),软考/面试高频加分项!

🧠 五、策略模式 vs 其他模式(面试高频对比)

对比项 策略模式 状态模式 模板方法
目的 封装可互换算法 对象行为随状态变化 定义算法骨架,子类实现步骤
客户端是否感知 是(主动切换策略) 否(状态自动切换) 否(调用固定模板)
类图结构 Context 持有 Strategy Context 与 State 双向依赖 抽象类 + 子类
典型场景 支付方式、排序算法 订单状态机(待支付→已支付→已发货) 数据处理流程(读→处理→写)

✅ 六、总结:为什么你必须掌握策略模式?

  1. 解决 if-else 膨胀:让代码从"面条"变"模块"
  2. 提升系统可扩展性:新增功能不改旧代码,符合架构师核心能力
  3. 软考高频考点:行为型模式代表,论文/案例分析常客
  4. 面试加分项:能结合工厂、注解、Spring 实战,体现工程思维

就像阿策所说:
"招式可换,心法不变。架构之道,亦在于此。"

相关推荐
小羊没烦恼!2 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里2 天前
java中的继承和多态的区别
java
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕2 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖2 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时2 天前
01-06-A-JVM排查实战详解
java·jvm
vipxieliang2 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
ba_pi2 天前
mysql 查询所有表名并授权
java
ProcessOn官方账号2 天前
java函数式编程--入门基础
java·编程·函数式编程