设计模式 - 工厂方法模式:解决生成对象时的不确定性

在这里插入图片描述

一、引言

设计模式 - 抽象工厂模式:统一不同代码风格下的代码级别中,我们介绍了抽象工厂模式,并结合家具厂与 Spring BeanFactory 实例,说明了如何寻找正确抽象。今天,我们继续深入工厂系列,学习更简单、使用频率更高的工厂方法模式(Factory Method Pattern)。该模式专注于围绕单一接口的对象创建,封装实例化过程,为项目带来更灵活、更易扩展的创建方式。

二、模式原理分析

定义:定义一个用于创建对象的接口,让实现该接口的类决定具体实例化哪个类。
目的:封装对象创建,提升方法可复用性,将实例化延迟到子类。

UML 三大角色

  1. 抽象产品(Product):声明所需产品的接口;
  2. 核心工厂(Creator):定义创建产品的抽象方法或静态方法;
  3. 具体产品(ConcreteProduct)/具体工厂(ConcreteCreator):实现抽象产品接口,并在工厂中实例化。
IProduct ←─────────── ProductFactory           Product_A_Impl  
   ▲                   │ getProduct(name)        implements IProduct  
   │                   └─── returns ConcreteProduct ─────────► use()  
Product_B_Impl  
implements IProduct  

三、代码实现示例

在这里插入图片描述

// 抽象产品
public interface IProduct {
    void apply();
}

// 核心工厂
public class ProductFactory {
    public static IProduct getProduct(String name) {
        if ("a".equals(name)) {
            return new ProductA();
        }
        return new ProductB();
    }
}

// 具体产品A
public class ProductA implements IProduct {
    @Override
    public void apply() {
        System.out.println("使用 A 产品");
    }
}

// 具体产品B
public class ProductB implements IProduct {
    @Override
    public void apply() {
        System.out.println("使用 B 产品");
    }
}

// 客户端调用
public static void main(String[] args) {
    IProduct p1 = ProductFactory.getProduct("");
    p1.apply();        // 使用 B 产品
    IProduct p2 = ProductFactory.getProduct("a");
    p2.apply();        // 使用 A 产品
}
  • 通过 ProductFactory.getProduct() 封装创建逻辑
  • 客户端只依赖 IProduct 接口,实现使用与创建分离

四、使用场景分析

工厂方法模式常见于:

  • 大量同类对象重复创建,如 DAO、VO 对象;
  • 创建依赖外部资源,如读取配置、获取授权;
  • 统一管理生命周期,如会话、浏览轨迹;
  • 池化对象,如连接池、线程池;
  • 隐藏真实类型,屏蔽复杂构造参数。

案例:MyBatis 的 LogFactory

MyBatis 通过 LogFactory 封装日志实现切换:

public interface Log { /* 原子操作方法 */ }
public final class LogFactory {
    private static Constructor<? extends Log> logConstructor;
    static {
        tryImplementation(LogFactory::useSlf4j);// 依次尝试不同日志实现
    }
    public static Log getLog(String name) {
        return logConstructor.newInstance(name);
    }
}
  • 核心工厂LogFactory
  • 抽象产品Log 接口
  • 具体产品Slf4jImplLog4jImplJdk14LoggingImpl
  • 增加新的日志框架,只需新增实现类并在静态初始化中注册

五、为什么要用工厂方法模式?

  1. 分离创建与使用,降低耦合,便于重构;
  2. 减少重复代码,将创建逻辑集中管理;
  3. 统一管理多种实现,扩展或切换只需修改工厂。

六、优缺点

优点

  • 根据需求定制化创建对象
  • 隐藏具体实现,提高可替换性(符合 LSP)
  • 满足开闭原则,易于扩展新的产品实现

缺点

  • 接口新增方法时,所有具体工厂需跟进,增加维护成本
  • 具体工厂实现可能各异,若缺乏统一规范,增加理解难度

七、总结与对比

  • 工厂方法模式:聚焦于单一抽象产品的继承扩展,适合简单场景;
  • 抽象工厂模式:侧重多种抽象产品的组合扩展,适合复杂系统。
    两者都封装了对象创建,但分别关注继承与组合两个维度。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小工匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值