策略模式和工厂模式的区别?

一则或许对你有用的小广告

欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于 Spring AI + Spring Boot3.x + JDK 21...点击查看;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot3.x + JDK 17...点击查看项目介绍; 演示链接: http://116.62.199.48:7070/;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/

面试考察点

面试官提出这个问题,其核心考察点不仅在于你是否能背诵两种模式的定义,更在于你是否真正理解了它们的设计哲学和应用场景。具体包括:

  1. 对两种模式核心思想的理解:你是否能从 “目的” 上区分它们,而不仅仅是 “结构”。
  2. 对应用场景的辨别能力:你是否能结合具体场景,说明在什么情况下该用策略模式,什么情况下该用工厂模式,这反映了你的设计决策能力。
  3. 对设计模式“组合使用”的认知:在实际项目中,模式往往不是孤立存在的。你是否理解它们如何协同工作,这是高级工程师的重要素质。

核心答案

策略模式和工厂模式的核心区别在于它们的目的和所解决的问题领域不同

  • 策略模式 是一种行为型设计模式,其核心目的是定义一系列算法(行为),并使它们可以相互替换。它关注的是 “做什么” 和 “怎么做” 的可变性,即行为的灵活切换
  • 工厂模式 是一种创建型设计模式,其核心目的是将对象的创建逻辑封装起来,与使用对象的代码解耦。它关注的是“创建谁”和“如何创建”的可变性,即对象创建的灵活性

简而言之:策略模式让 “行为” 易于切换,而工厂模式让 “对象” 易于创建。

深度解析

原理/机制

  • 策略模式:定义一个公共的策略接口(Strategy),不同的具体策略类(ConcreteStrategy)实现这个接口,提供不同的算法实现。上下文类(Context)持有一个策略接口的引用,并通过此引用调用具体策略,从而实现在运行时动态改变其行为。
  • 工厂模式:定义一个创建对象的接口(Factory),但将具体实例化哪个类的决定延迟到子类(ConcreteFactory)。调用者无需关心对象的具体创建细节,只需通过工厂接口获取所需产品(Product)。

代码示例:电商场景下的对比

假设我们有一个电商下单系统。

1. 使用策略模式(处理不同的折扣计算方式) 策略模式在这里用于处理 “如何计算折扣” 这个行为的变化。

// 策略接口:定义“计算折扣”这个行为
interface DiscountStrategy {
    double calculateDiscount(double originalPrice);
}

// 具体策略:无折扣
class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public double calculateDiscount(double originalPrice) {
        return originalPrice;
    }
}

// 具体策略:固定折扣
class FixedDiscountStrategy implements DiscountStrategy {
    private double discountAmount;
    public FixedDiscountStrategy(double amount) { this.discountAmount = amount; }
    @Override
    public double calculateDiscount(double originalPrice) {
        return Math.max(0, originalPrice - discountAmount);
    }
}

// 上下文:订单
class Order {
    private DiscountStrategy discountStrategy; // 持有策略引用
    private double price;

    public void setDiscountStrategy(DiscountStrategy strategy) {
        this.discountStrategy = strategy;
    }

    public double getFinalPrice() {
        // 委托给具体的策略对象执行计算
        return discountStrategy.calculateDiscount(this.price);
    }
}

// 使用
public class Client {
    public static void main(String[] args) {
        Order order = new Order();
        order.setPrice(100.0);
        
        // 运行时动态切换行为
        order.setDiscountStrategy(new NoDiscountStrategy());
        System.out.println("无折扣价:" + order.getFinalPrice()); // 输出 100.0
        
        order.setDiscountStrategy(new FixedDiscountStrategy(20.0));
        System.out.println("固定折扣价:" + order.getFinalPrice()); // 输出 80.0
    }
}

2. 使用工厂模式(创建不同类型的订单对象) 工厂模式在这里用于处理 “创建哪种订单” 这个对象的变化。

// 产品接口
interface Order {
    void process();
}

// 具体产品:普通订单
class NormalOrder implements Order {
    @Override
    public void process() { System.out.println("处理普通订单..."); }
}

// 具体产品:团购订单
class GroupBuyOrder implements Order {
    @Override
    public void process() { System.out.println("处理团购订单..."); }
}

// 工厂接口
interface OrderFactory {
    Order createOrder();
}

// 具体工厂
class NormalOrderFactory implements OrderFactory {
    @Override
    public Order createOrder() { return new NormalOrder(); }
}
class GroupBuyOrderFactory implements OrderFactory {
    @Override
    public Order createOrder() { return new GroupBuyOrder(); }
}

// 使用
public class Client {
    public static void main(String[] args) {
        // 根据业务类型选择不同的工厂
        OrderFactory factory = getFactoryByType("GROUP_BUY");
        Order order = factory.createOrder(); // 创建过程被封装
        order.process(); // 输出 “处理团购订单...”
    }
    private static OrderFactory getFactoryByType(String type) {
        // 根据type返回对应的工厂实例
        return new GroupBuyOrderFactory();
    }
}

对比分析与最佳实践

维度策略模式 (Strategy)工厂模式 (Factory)
目的封装可互换的算法或行为,实现行为在运行时的灵活切换。封装对象的创建过程,将客户端与具体类解耦。
关注点怎么做” (How)创建谁” (Who)
典型场景支付方式(支付宝、微信、信用卡)、折扣算法、排序算法、数据压缩格式等。连接不同类型数据库(MySQL、Oracle工厂)、日志记录器(File、Console工厂)、UI主题工厂等。
最佳实践当系统中一个类有多种行为变体,且需要在运行时根据条件选择其一。当创建对象的逻辑复杂,或希望将创建代码与业务逻辑分离以提高可维护性。
组合使用非常常见。例如,一个由 “工厂” 创建的 “订单” 对象,其内部的 “折扣计算” 行为可以通过 “策略模式” 来配置。这体现了模式的强大组合能力。

常见误区

  • 误区一:认为策略模式就是简单的 if-else 替换。策略模式的核心在于将行为抽象并委托,它消除了庞大的条件语句,并使增加新策略变得非常容易(符合开闭原则)。
  • 误区二:混淆 “简单工厂” 和策略模式。简单工厂方法返回的是对象,而策略模式返回的是行为(算法)。一个常见的错误设计是,策略的 Context 类自己去创建具体的策略对象,这实际上混入了工厂的职责,耦合了创建逻辑。最佳实践是,策略对象本身可以通过依赖注入(如 Spring)或工厂模式来创建,以实现更高的解耦。

总结

策略模式的核心是封装变化的行为,实现运行时的算法替换;而工厂模式的核心是封装对象的创建,将实例化逻辑与使用分离。理解它们本质目的的不同,是正确选择和运用这两种模式的关键。在复杂系统中,二者常协同工作,策略对象本身很可能由工厂来创建。