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

文章目录

  • 前言
  • 一、概念
  • 二、核心思想
  • 三、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()是工厂方法的经典应用,理解其设计思路可举一反三。
相关推荐
杨充21 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充21 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充21 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充21 小时前
2.面向对象的特性
设计模式
杨充21 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充21 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充21 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式