目录

一、先搞懂两个基础模式

1. 策略模式

2. 工厂模式

3. 策略工厂模式(最终形态)

二、适用场景

三、标准结构(5 个角色)

四、Java 代码实现(完整可运行)

1. 定义策略接口(统一行为)

2. 实现具体策略(多种逻辑)

支付宝支付

微信支付

银行卡支付

3. 核心:策略工厂(关键!)

4. (可选)策略上下文

5. 客户端调用(测试)

运行结果

五、如何扩展新策略?(体现优势)

六、策略工厂模式的优点

七、和纯策略模式的区别

八、进阶优化(企业级用法)

总结


策略工厂模式 = 策略模式(Strategy) + 工厂模式(Factory),是开发中最常用的设计模式组合之一,专门解决:同一行为,多种实现,动态切换的场景(比如支付方式切换、优惠策略切换、文件解析方式切换)。


一、先搞懂两个基础模式

1. 策略模式

  • 核心:定义一组算法(策略),分别封装,让它们可以互相替换。
  • 解决:大量 if-else / switch 判断不同实现逻辑的问题。
  • 缺点:需要自己创建策略对象,还得自己管理用哪个策略。

2. 工厂模式

  • 核心:专门负责创建对象,屏蔽创建细节。
  • 解决:策略模式中手动 new 对象、硬编码判断策略的问题。

3. 策略工厂模式(最终形态)

  • 工厂负责:创建、管理所有策略(存到 Map 里,根据类型直接取)。
  • 策略负责:自己的业务逻辑
  • 调用方:只需要传入类型,直接执行,无任何 if-else

二、适用场景

你只要遇到下面这些情况,直接用策略工厂:

  1. 一个操作有多种实现方式(微信支付、支付宝、银行卡支付)。
  2. 需要动态切换算法 / 策略。
  3. 不想写一堆 if (type == 1) {...} else if (type == 2) {...}
  4. 方便扩展新策略(加一个策略不用改旧代码,符合开闭原则)。

三、标准结构(5 个角色)

角色 作用
Strategy 策略接口 定义所有策略必须实现的方法
ConcreteStrategy 具体策略 实现接口,写各自的业务逻辑
StrategyFactory 策略工厂 单例,管理所有策略,提供根据类型获取策略的方法
StrategyContext 策略上下文(可选) 封装调用,解耦调用方和策略
Client 调用方 使用工厂获取策略,执行逻辑

四、Java 代码实现(完整可运行)

我们用支付场景举例:

  • 策略:微信支付、支付宝支付、银行卡支付
  • 工厂:统一管理这些支付策略

1. 定义策略接口(统一行为)

/**
 * 支付策略接口
 */
public interface PaymentStrategy {
    // 支付方法
    void pay(double amount);
}

2. 实现具体策略(多种逻辑)

支付宝支付
public class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付:" + amount + " 元");
    }
}
微信支付
public class WechatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付:" + amount + " 元");
    }
}
银行卡支付
public class BankCardPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用银行卡支付:" + amount + " 元");
    }
}

3. 核心:策略工厂(关键!)

  • Map 存储所有策略(类型 -> 策略对象)
  • 提供静态方法根据类型获取策略
  • 天然消除 if-else
import java.util.HashMap;
import java.util.Map;

/**
 * 支付策略工厂(单例)
 */
public class PaymentFactory {
    // 1. 注册所有策略:key=支付类型,value=对应策略对象
    private static final Map<String, PaymentStrategy> PAYMENT_MAP = new HashMap<>();

    // 2. 静态代码块:项目启动时就把所有策略注册好
    static {
        PAYMENT_MAP.put("ALIPAY", new AlipayStrategy());
        PAYMENT_MAP.put("WECHAT", new WechatPayStrategy());
        PAYMENT_MAP.put("BANK_CARD", new BankCardPayStrategy());
    }

    // 3. 核心方法:根据类型获取策略(没有 if-else!)
    public static PaymentStrategy getPayment(String type) {
        if (type == null || !PAYMENT_MAP.containsKey(type)) {
            throw new IllegalArgumentException("不支持的支付方式");
        }
        return PAYMENT_MAP.get(type);
    }
}

4. (可选)策略上下文

封装调用,让代码更优雅:

/**
 * 支付上下文:调用方直接用这个类
 */
public class PaymentContext {
    private final PaymentStrategy strategy;

    // 构造时从工厂获取策略
    public PaymentContext(String type) {
        this.strategy = PaymentFactory.getPayment(type);
    }

    // 执行支付
    public void executePay(double amount) {
        strategy.pay(amount);
    }
}

5. 客户端调用(测试)

public class Client {
    public static void main(String[] args) {
        // 支付宝支付
        PaymentContext context1 = new PaymentContext("ALIPAY");
        context1.executePay(100);

        // 微信支付
        PaymentContext context2 = new PaymentContext("WECHAT");
        context2.executePay(200);

        // 银行卡支付
        PaymentContext context3 = new PaymentContext("BANK_CARD");
        context3.executePay(500);
    }
}

运行结果

使用支付宝支付:100.0 元
使用微信支付:200.0 元
使用银行卡支付:500.0 元

五、如何扩展新策略?(体现优势)

假如现在要加云闪付完全不用修改旧代码

  1. 新增策略类:
public class UnionPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用云闪付支付:" + amount + " 元");
    }
}
  1. 在工厂的 static 块里加一行注册:
PAYMENT_MAP.put("UNION_PAY", new UnionPayStrategy());
  1. 直接调用:
new PaymentContext("UNION_PAY").executePay(300);

符合开闭原则:对扩展开放,对修改关闭


六、策略工厂模式的优点

  1. 消除大量 if-else:代码干净、可读性极高
  2. 易于扩展:加新策略只加类 + 注册,不改动旧代码
  3. 职责清晰
    • 策略:只管自己的逻辑
    • 工厂:只管创建和管理
  4. 可动态切换:运行时根据类型自由换策略
  5. 符合设计原则:单一职责、开闭原则

七、和纯策略模式的区别

  • 纯策略模式:你要自己 new AlipayStrategy()、自己判断类型
  • 策略工厂模式:工厂帮你管理所有策略,你只传类型,直接用

八、进阶优化(企业级用法)

实际项目中,我们会用 注解 + 自动扫描 代替手动注册:

  1. 定义 @PayType("ALIPAY") 注解
  2. 项目启动时自动扫描所有策略类
  3. 自动注册到工厂 Map
  4. 完全不用改工厂代码

总结

  1. 策略工厂 = 策略(做什么) + 工厂(怎么拿)
  2. 核心是 Map 存储策略 + 根据类型直接获取
  3. 解决:多实现、动态切换、消灭 if-else
  4. 扩展方便、代码优雅、企业最常用

更多推荐