【设计模式】创建型-工厂方法模式

文章目录

  • 前言
  • 一、概念
  • 二、核心思想
  • 三、Java代码实现
    • [1. 定义抽象产品(日志记录器接口)](#1. 定义抽象产品(日志记录器接口))
    • [2. 定义具体产品(文件日志/数据库日志)](#2. 定义具体产品(文件日志/数据库日志))
    • [3. 定义抽象工厂(日志工厂接口)](#3. 定义抽象工厂(日志工厂接口))
    • [4. 定义具体工厂(文件日志工厂/数据库日志工厂)](#4. 定义具体工厂(文件日志工厂/数据库日志工厂))
    • [5. 客户端使用代码](#5. 客户端使用代码)
    • [6. 扩展:新增Redis日志(符合开闭原则)](#6. 扩展:新增Redis日志(符合开闭原则))
  • 四、优缺点
    • [1. 优点](#1. 优点)
    • [2. 缺点](#2. 缺点)
  • 五、应用场景
  • 六、注意事项
  • 总结

前言

在AI时代,代码的编写可以被大模型辅助甚至替代,但程序员真正的核心竞争力是技术思维------设计模式这类沉淀了数十年的"内功心法",决定了代码的可维护性、扩展性和稳定性,是AI无法完全替代的核心能力。工厂方法模式作为创建型模式的核心,解决了"对象创建与业务逻辑耦合"的问题,是解耦对象创建的基础范式。

一、概念

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,定义了一个创建对象的接口,但让实现这个接口的子类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行,核心是"将对象的创建权交给子类"。

简单来说,工厂方法模式把"创建什么对象"的判断逻辑,从主业务逻辑中抽离,交给专门的工厂类处理,让主程序只关注"使用对象",而非"创建对象"。

二、核心思想

  1. 抽象产品:定义产品的通用接口/抽象类,规范产品的核心行为;
  2. 具体产品:实现抽象产品接口,是最终被创建的对象;
  3. 抽象工厂:定义创建产品的抽象方法,声明返回抽象产品类型;
  4. 具体工厂:实现抽象工厂的创建方法,返回具体产品实例,决定创建哪种产品。

工厂方法模式的核心本质是**"开闭原则"的体现**------新增产品时,无需修改原有工厂和业务代码,只需新增"具体产品+具体工厂",符合"对扩展开放、对修改关闭"。

三、Java代码实现

以"日志记录器"场景为例:系统需要支持文件日志、数据库日志两种记录方式,后续可能扩展Redis日志,用工厂方法模式实现解耦。

1. 定义抽象产品(日志记录器接口)

java 复制代码
/**
 * 抽象产品:日志记录器接口
 * 定义所有日志记录器的通用行为
 */
public interface Logger {
    // 日志记录方法
    void log(String message);
}

2. 定义具体产品(文件日志/数据库日志)

java 复制代码
/**
 * 具体产品:文件日志记录器
 */
public class FileLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("【文件日志】:" + message);
    }
}

/**
 * 具体产品:数据库日志记录器
 */
public class DatabaseLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("【数据库日志】:" + message);
    }
}

3. 定义抽象工厂(日志工厂接口)

java 复制代码
/**
 * 抽象工厂:日志记录器工厂接口
 * 定义创建日志记录器的抽象方法
 */
public interface LoggerFactory {
    // 创建日志记录器的工厂方法
    Logger createLogger();
}

4. 定义具体工厂(文件日志工厂/数据库日志工厂)

java 复制代码
/**
 * 具体工厂:文件日志工厂
 * 负责创建文件日志记录器实例
 */
public class FileLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        // 可在此添加文件日志器的初始化逻辑(如创建文件、配置路径)
        return new FileLogger();
    }
}

/**
 * 具体工厂:数据库日志工厂
 * 负责创建数据库日志记录器实例
 */
public class DatabaseLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        // 可在此添加数据库日志器的初始化逻辑(如建立数据库连接)
        return new DatabaseLogger();
    }
}

5. 客户端使用代码

java 复制代码
/**
 * 客户端:业务逻辑层
 * 只关注使用日志器,不关注创建细节
 */
public class Client {
    public static void main(String[] args) {
        // 1. 创建文件日志工厂
        LoggerFactory fileFactory = new FileLoggerFactory();
        // 2. 通过工厂创建文件日志器
        Logger fileLogger = fileFactory.createLogger();
        fileLogger.log("用户登录成功");

        // 1. 创建数据库日志工厂
        LoggerFactory dbFactory = new DatabaseLoggerFactory();
        // 2. 通过工厂创建数据库日志器
        Logger dbLogger = dbFactory.createLogger();
        dbLogger.log("用户下单失败");
    }
}

输出结果:

复制代码
【文件日志】:用户登录成功
【数据库日志】:用户下单失败

6. 扩展:新增Redis日志(符合开闭原则)

java 复制代码
// 1. 新增具体产品:Redis日志记录器
public class RedisLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("【Redis日志】:" + message);
    }
}

// 2. 新增具体工厂:Redis日志工厂
public class RedisLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        return new RedisLogger();
    }
}

// 3. 客户端使用(无需修改原有代码)
public class Client {
    public static void main(String[] args) {
        LoggerFactory redisFactory = new RedisLoggerFactory();
        Logger redisLogger = redisFactory.createLogger();
        redisLogger.log("系统启动完成");
    }
}

四、优缺点

1. 优点

  1. 解耦创建与使用:业务逻辑只关注产品的使用,创建逻辑由工厂类负责,代码职责更清晰;
  2. 符合开闭原则:新增产品时,只需新增"具体产品+具体工厂",无需修改原有代码;
  3. 提高代码可维护性:产品创建逻辑集中在工厂类,后续修改创建规则(如初始化参数)只需改工厂,无需改所有使用处;
  4. 隐藏产品细节:客户端仅依赖抽象产品和抽象工厂,无需知道具体产品的实现细节。

2. 缺点

  1. 类数量膨胀:每新增一个产品,需同时新增具体产品类和具体工厂类,系统类数量会成倍增加;
  2. 增加系统复杂度:简单场景下使用工厂方法,会引入额外的抽象层和工厂类,增加理解成本;
  3. 抽象层设计难度高:若抽象产品/工厂设计不合理,后续扩展可能需要修改抽象层,违背开闭原则。

五、应用场景

工厂方法模式适用于对象创建逻辑复杂、产品类型易扩展的场景:

  1. 框架扩展场景 :Java集合的Collection.iterator()方法(子类ArrayList/HashSet实现自己的迭代器工厂);
  2. 日志/存储扩展:如示例中的多类型日志记录、多数据源(MySQL/Oracle/Redis)连接创建;
  3. 插件化开发:系统支持多种插件,每种插件对应一个工厂类,新增插件只需新增插件类和工厂类;
  4. 复杂对象创建:对象创建需要初始化参数、资源加载等复杂逻辑,将这些逻辑封装在工厂中;
  5. 跨平台适配:如不同操作系统的UI组件(WindowsButton/LinuxButton),由对应工厂创建。

六、注意事项

  1. 避免过度设计:简单场景(产品类型固定、创建逻辑简单)无需使用工厂方法,直接new更简洁;
  2. 抽象层设计:抽象产品/工厂需提炼通用行为,避免包含具体产品的特有方法,否则客户端仍需强转;
  3. 工厂的单一职责:每个具体工厂只负责创建一种产品,避免一个工厂创建多种产品导致逻辑混乱;
  4. 与简单工厂的区别:简单工厂是"一个工厂创建所有产品"(违背开闭),工厂方法是"一个工厂对应一个产品"(符合开闭)。

总结

  1. 工厂方法模式核心是将对象创建推迟到子类,通过"抽象产品+抽象工厂"解耦创建与使用,符合开闭原则;
  2. 优势是扩展灵活、职责清晰,缺点是类数量膨胀,需根据场景选择(产品易扩展时优先使用);
  3. Java标准库中Collection.iterator()是工厂方法的经典应用,理解其设计思路可举一反三。
相关推荐
我爱学习_zwj2 小时前
设计模式-2(单例模式与原型模式)
前端·javascript·设计模式
砍光二叉树3 小时前
【设计模式】创建型-单例模式
单例模式·设计模式
我爱学习_zwj3 小时前
设计模式-3(装饰器模式)
前端·设计模式·装饰器模式
文心快码BaiduComate18 小时前
Comate内置模型已支持 MiniMax-M2.7!
设计模式·程序员·前端框架
console.log('npc')19 小时前
Cursor,Trae,Claude Code如何协作生产出一套前后台app?
前端·人工智能·react.js·设计模式·ai·langchain·ai编程
czxyvX1 天前
C++ - 基于多设计模式下的同步&异步日志系统
c++·设计模式
蒸蒸yyyyzwd1 天前
设计模式之美学习笔记
笔记·学习·设计模式
双手插兜-装高手1 天前
C++设计模式
c++·设计模式
sevenlin2 天前
Spring Boot 经典九设计模式全览
java·spring boot·设计模式