工厂模式:解耦对象创建与使用的设计模式

工厂模式:解耦对象创建与使用的设计模式

一、模式核心:封装对象创建逻辑,客户端无需关心具体实现

在软件开发中,当创建对象的逻辑复杂或频繁变化时,直接在客户端代码中 new 对象会导致耦合度高、难以维护。例如,创建不同类型的日志记录器(文件日志、数据库日志)时,客户端若直接依赖具体类,后续新增日志类型需修改所有调用处。

工厂模式(Factory Pattern) 通过引入一个工厂类,将对象的创建逻辑封装起来,客户端只需通过工厂类获取对象,无需知道对象的具体创建过程。核心解决:

  • 解耦创建与使用:客户端与具体产品类解耦,专注于业务逻辑。
  • 集中管理创建逻辑:对象创建规则统一在工厂类中维护,便于修改和扩展。
  • 符合开闭原则:新增产品类型时,只需扩展工厂类,无需修改现有客户端代码。

核心角色

  1. 抽象产品(Product) :定义产品的公共接口(如日志记录器的log()方法)。
  2. 具体产品(Concrete Product) :实现抽象产品接口,如FileLogger、DatabaseLogger。
  3. 工厂类(Factory):负责创建具体产品实例,返回抽象产品类型。

核心思想与 UML 类图

二、核心实现:日志记录器工厂

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);  
    }  
}  
数据库日志记录器
java 复制代码
public class DatabaseLogger implements Logger {  
    @Override  
    public void log(String message) {  
        System.out.println("数据库日志:" + message);  
    }  
}  

3. 实现工厂类

java 复制代码
public class LoggerFactory {  
    // 根据类型创建日志记录器  
    public static Logger createLogger(String type) {  
        switch (type.toUpperCase()) {  
            case "FILE":  
                return new FileLogger();  
            case "DATABASE":  
                return new DatabaseLogger();  
            default:  
                throw new IllegalArgumentException("不支持的日志类型:" + type);  
        }  
    }  
}  

4. 客户端调用

java 复制代码
public class ClientDemo {  
    public static void main(String[] args) {  
        // 通过工厂获取文件日志记录器  
        Logger fileLogger = LoggerFactory.createLogger("file");  
        fileLogger.log("系统启动");  

        // 通过工厂获取数据库日志记录器  
        Logger dbLogger = LoggerFactory.createLogger("database");  
        dbLogger.log("用户登录");  
    }  
}  

输出结果:

plaintext 复制代码
文件日志:系统启动  
数据库日志:用户登录  

三、扩展:参数化配置实现动态工厂

为避免硬编码产品类型,可通过配置文件(如config.properties)动态指定产品类,提升灵活性。

1. 创建配置文件(src/config.properties)

properties 复制代码
logger.type=file  

2. 修改工厂类读取配置

java 复制代码
import java.io.IOException;  
import java.util.Properties;  

public class LoggerFactory {  
    private static final String CONFIG_FILE = "config.properties";  

    public static Logger createLogger() {  
        try {  
            // 读取配置文件  
            Properties prop = new Properties();  
            prop.load(LoggerFactory.class.getClassLoader().getResourceAsStream(CONFIG_FILE));  
            String type = prop.getProperty("logger.type");  

            // 根据配置创建产品  
            switch (type.toUpperCase()) {  
                case "FILE":  
                    return new FileLogger();  
                case "DATABASE":  
                    return new DatabaseLogger();  
                default:  
                    throw new IllegalArgumentException("配置错误:未知日志类型");  
            }  
        } catch (IOException e) {  
            throw new RuntimeException("加载配置失败", e);  
        }  
    }  
}  

3. 客户端简化调用

java 复制代码
public class ClientDemo {  
    public static void main(String[] args) {  
        Logger logger = LoggerFactory.createLogger(); // 自动根据配置创建  
        logger.log("动态加载的日志记录器");  
    }  
}  

四、工厂模式 vs 抽象工厂模式

对比维度 工厂模式 抽象工厂模式
处理对象 单一产品类型(如 Logger) 产品族(如 Logger + LogAnalyzer)
扩展性 新增产品需修改工厂类 新增产品族只需扩展新工厂
复杂度 简单,适合小型场景 复杂,适合多产品族的大型系统
典型场景 单一类型对象创建(如日志、数据库连接) 跨平台组件(如 Windows/Linux 界面组件)

五、适用场景

场景 示例 优势
对象创建逻辑复杂 涉及参数校验、资源初始化的对象 封装复杂逻辑,避免客户端臃肿
多类型产品切换 不同环境下使用不同实现(如测试 / 生产环境) 客户端无需修改,通过工厂动态切换
遵循迪米特法则 减少客户端与具体类的直接依赖 降低耦合度,提升可维护性

六、总结

工厂模式通过 "封装创建,暴露接口" 的设计,使客户端代码更简洁、可维护性更高。它是创建型模式的基础,在 Java 集合框架(如Calendar.getInstance())、Spring 框架(Bean 工厂)中广泛应用。

扩展思考:

  • 工厂模式有哪些变种?(如静态工厂、工厂方法模式)
  • 如何结合反射机制进一步优化工厂类?
相关推荐
追逐时光者17 分钟前
一款基于 .NET 开源、免费的数据库自治诊断平台
后端·.net
nice_lcj52018 分钟前
Java 并发容器入门:ConcurrentHashMap、CopyOnWriteArrayList、阻塞队列
java·面试·并发编程·阻塞队列·concurrenthashmap·copyonwritearraylist
微小的鱼29 分钟前
Linux的渲染与显示系统链路
android·java·linux
追逐时光者31 分钟前
让 GitHub Copilot 更懂你的 .NET 代码风格:一份精简实用的 Copilot Instructions
后端·.net
小满zs1 小时前
Go语言第十八章(架构设计)
后端·go
若亦_1 小时前
Java中关于this的三种用法
java·开发语言·intellij-idea
山甫aa1 小时前
锁一篇搞定:乐观锁、悲观锁、CAS、数据库锁与分布式锁【从零开始的 Web 后端学习】
java·数据库·分布式·后端·学习·web
软件技术NINI1 小时前
基于SpringBoot和Vue的博物馆预约平台管理系统的设计与实现
java·毕业设计·毕设
IT_陈寒2 小时前
Java开发实战:从入门到精通
前端·人工智能·后端
jktantan2 小时前
注解式脱敏:用 Jackson 的 ContextualSerializer 做字段级策略(一)
spring boot·后端·算法·spring cloud·系统架构