【设计模式】工厂方法模式(Factory Method)详解:从简单工厂到真正的“面向扩展”

文章目录

    • [1. 引言:简单工厂的问题在哪里?](#1. 引言:简单工厂的问题在哪里?)
    • [2. 什么是工厂方法模式](#2. 什么是工厂方法模式)
    • [3. 工厂方法模式的角色组成](#3. 工厂方法模式的角色组成)
    • [4. 示例场景:日志系统](#4. 示例场景:日志系统)
    • [5. 抽象产品](#5. 抽象产品)
    • [6. 具体产品实现](#6. 具体产品实现)
    • [7. 抽象工厂](#7. 抽象工厂)
    • [8. 具体工厂实现](#8. 具体工厂实现)
    • [9. 客户端使用方式](#9. 客户端使用方式)
    • [10. 与简单工厂的对比](#10. 与简单工厂的对比)
    • [11. 工厂方法模式的优点](#11. 工厂方法模式的优点)
    • [12. 工厂方法模式的缺点](#12. 工厂方法模式的缺点)
    • [13. 适用场景](#13. 适用场景)
    • [14. JDK 中的工厂方法模式](#14. JDK 中的工厂方法模式)
    • 参考

1. 引言:简单工厂的问题在哪里?

我在上一篇文章中,介绍了简单工厂模式 简单工厂模式介绍-CSDN博客。它通过一个工厂类集中创建对象,确实解决了对象创建与使用耦合的问题。

但它也有一个致命缺陷:

每增加一种产品,就必须修改工厂类。

java 复制代码
switch (type) {
    case "A": return new ProductA();
    case "B": return new ProductB();
}

这直接违反了 开闭原则(OCP)

对扩展开放,对修改关闭。

于是,一个更"面向对象"的创建模式出现了 ------ 工厂方法模式


2. 什么是工厂方法模式

定义(GoF)

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

一句话理解:

把"选择 new 哪个对象"的权力,从 if-else,交给不同的工厂子类。

如果简单工厂让你频繁改 switch,那你需要工厂方法模式。


3. 工厂方法模式的角色组成

工厂方法模式通常包含四个角色:

  1. 抽象产品(Product)

定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。

  1. 具体产品(ConcreteProduct)

实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

  1. 抽象工厂(Factory)

提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。

  1. 具体工厂(ConcreteFactory)

主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。

结构示意:


4. 示例场景:日志系统

假设我们要支持多种日志方式:

  • 文件日志
  • 数据库日志

5. 抽象产品

java 复制代码
public interface Logger {
    void writeLog(String message);
}

6. 具体产品实现

文件日志

java 复制代码
public class FileLogger implements Logger {
    @Override
    public void writeLog(String message) {
        System.out.println("写入文件日志:" + message);
    }
}

数据库日志

java 复制代码
public class DatabaseLogger implements Logger {
    @Override
    public void writeLog(String message) {
        System.out.println("写入数据库日志:" + message);
    }
}

7. 抽象工厂

java 复制代码
public interface LoggerFactory {
    Logger createLogger();
}

8. 具体工厂实现

文件日志工厂

java 复制代码
public class FileLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        return new FileLogger();
    }
}

数据库日志工厂

java 复制代码
public class DatabaseLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        return new DatabaseLogger();
    }
}

9. 客户端使用方式

java 复制代码
public class Client {
    public static void main(String[] args) {
        LoggerFactory factory = new FileLoggerFactory();
        Logger logger = factory.createLogger();
        logger.writeLog("系统启动");
    }
}

客户端此时的特点:

  • 不再关心具体产品类
  • 只依赖抽象接口
  • 更换产品只需更换工厂实现

10. 与简单工厂的对比

维度 简单工厂 工厂方法
是否使用继承
是否违反 OCP
工厂数量 一个 多个
扩展方式 修改工厂 新增工厂
系统复杂度

11. 工厂方法模式的优点

  1. 符合开闭原则
  2. 避免 if-else 判断
  3. 扩展性强
  4. 客户端与具体产品解耦
  5. 更符合面向对象设计

12. 工厂方法模式的缺点

  1. 类的数量明显增多
  2. 系统结构更加复杂
  3. 对小型项目可能"过度设计"

13. 适用场景

适合使用

  • 产品类型经常扩展
  • 不希望频繁修改已有代码
  • 框架级开发
  • 日志、消息、解析器等组件

不适合使用

  • 产品种类固定
  • 系统规模较小
  • 追求极简实现的场景

14. JDK 中的工厂方法模式

Collection.iterator()

java 复制代码
Iterator<E> iterator();
  • 不同集合返回不同迭代器
  • 调用方不关心具体实现类

这是典型的工厂方法思想。


参考

工厂方法 - Java教程 - 廖雪峰的官方网站

工厂模式 | 菜鸟教程

相关推荐
蔺太微17 小时前
桥接模式(Bridge Pattern)
设计模式·桥接模式
zhaokuner17 小时前
14-有界上下文-DDD领域驱动设计
java·开发语言·设计模式·架构
Geoking.20 小时前
【设计模式】抽象工厂模式(Abstract Factory)详解:一次创建“一整套产品”
设计模式·抽象工厂模式
zhaokuner1 天前
12-深层模型与重构-DDD领域驱动设计
java·开发语言·设计模式·架构
不加糖4351 天前
设计模式 -- 适配器 & 策略模式
python·设计模式
__万波__1 天前
二十三种设计模式(十九)--备忘录模式
java·设计模式·备忘录模式
killer_queen48041 天前
设计模式-观察者模式
观察者模式·设计模式
Yu_Lijing1 天前
基于C++的《Head First设计模式》笔记——观察者模式
c++·笔记·设计模式