Java设计模式 二十六 工厂模式 + 单例模式

工厂模式 + 单例模式

工厂模式单例模式的组合是一种常见的设计模式组合,通常用于确保某些全局共享的资源(如配置管理器、数据库连接池等)只有一个实例,同时通过工厂方法提供统一的对象创建方式。


1. 场景说明

工厂模式用于创建对象,提供了一种灵活的对象实例化方式。单例模式用于确保某个类只有一个实例,并提供全局访问点。两者的结合通常应用于以下场景:

  • 数据库连接工厂: 确保数据库连接池只有一个工厂实例,同时提供连接对象的创建。
  • 配置管理器: 确保配置管理器类只有一个实例,通过工厂方法管理不同的配置对象。
  • 日志系统: 确保日志管理器只有一个实例,同时根据需要生成不同类型的日志记录器。

2. 模式组合的优点

  1. 唯一性: 单例模式保证工厂类的唯一性,避免了工厂类被多次实例化。
  2. 扩展性: 工厂模式为创建对象提供了灵活性,可以通过多态或其他扩展方式动态创建不同类型的对象。
  3. 全局访问: 单例模式提供了全局访问点,工厂模式集中管理对象的创建逻辑,二者结合使得系统结构清晰。

3. 实现示例:数据库连接工厂

以下示例展示了一个数据库连接工厂的实现,工厂类采用单例模式,确保只有一个工厂实例。


(1) 数据库连接类

数据库连接类表示单个连接对象。

java 复制代码
// 数据库连接类
public class DatabaseConnection {
    private String connectionString;

    public DatabaseConnection(String connectionString) {
        this.connectionString = connectionString;
    }

    public void connect() {
        System.out.println("连接到数据库: " + connectionString);
    }
}

(2) 工厂类

工厂类使用单例模式,确保只有一个工厂实例,负责创建数据库连接对象。

java 复制代码
// 工厂类
public class DatabaseConnectionFactory {
    // 单例实例
    private static DatabaseConnectionFactory instance;

    // 私有构造方法
    private DatabaseConnectionFactory() {}

    // 获取单例实例
    public static DatabaseConnectionFactory getInstance() {
        if (instance == null) {
            synchronized (DatabaseConnectionFactory.class) { // 线程安全的单例
                if (instance == null) {
                    instance = new DatabaseConnectionFactory();
                }
            }
        }
        return instance;
    }

    // 工厂方法:创建数据库连接
    public DatabaseConnection createConnection(String connectionString) {
        return new DatabaseConnection(connectionString);
    }
}

(3) 客户端代码

客户端代码通过单例工厂创建数据库连接对象。

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 获取工厂实例
        DatabaseConnectionFactory factory = DatabaseConnectionFactory.getInstance();

        // 创建数据库连接
        DatabaseConnection connection1 = factory.createConnection("jdbc:mysql://localhost:3306/db1");
        connection1.connect();

        DatabaseConnection connection2 = factory.createConnection("jdbc:postgresql://localhost:5432/db2");
        connection2.connect();

        // 确保工厂是单例
        DatabaseConnectionFactory anotherFactory = DatabaseConnectionFactory.getInstance();
        System.out.println(factory == anotherFactory); // 输出: true
    }
}

运行结果:
连接到数据库: jdbc:mysql://localhost:3306/db1
连接到数据库: jdbc:postgresql://localhost:5432/db2
true

4. 扩展示例:多类型对象的工厂

在某些场景下,工厂需要根据不同的参数创建不同类型的对象,工厂模式和单例模式的结合依然适用。例如:日志管理系统。


(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 ConsoleLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("控制台日志记录: " + message);
    }
}

(3) 单例工厂类
java 复制代码
// 日志工厂类
public class LoggerFactory {
    private static LoggerFactory instance;

    private LoggerFactory() {}

    public static LoggerFactory getInstance() {
        if (instance == null) {
            synchronized (LoggerFactory.class) {
                if (instance == null) {
                    instance = new LoggerFactory();
                }
            }
        }
        return instance;
    }

    public Logger createLogger(String type) {
        if ("file".equalsIgnoreCase(type)) {
            return new FileLogger();
        } else if ("console".equalsIgnoreCase(type)) {
            return new ConsoleLogger();
        } else {
            throw new IllegalArgumentException("未知的日志类型: " + type);
        }
    }
}

(4) 客户端代码
java 复制代码
public class Client {
    public static void main(String[] args) {
        LoggerFactory loggerFactory = LoggerFactory.getInstance();

        Logger fileLogger = loggerFactory.createLogger("file");
        fileLogger.log("这是文件日志");

        Logger consoleLogger = loggerFactory.createLogger("console");
        consoleLogger.log("这是控制台日志");
    }
}

运行结果:
文件日志记录: 这是文件日志
控制台日志记录: 这是控制台日志

5. 优缺点

优点:
  1. 全局唯一性: 单例模式确保工厂类唯一,全局共享。
  2. 灵活扩展: 工厂模式使得对象创建逻辑集中在工厂类中,新增对象类型时无需修改客户端代码。
  3. 高效管理: 工厂和单例结合能够高效管理系统中的全局资源,例如数据库连接、日志管理器等。
缺点:
  1. 复杂性增加: 模式组合会增加系统的复杂度,可能引入过度设计的问题。
  2. 线程安全性: 单例模式需要考虑多线程环境下的安全性,增加了实现的复杂性。

6. 总结

工厂模式 + 单例模式的组合是一种常见的设计模式组合,用于解决全局唯一资源的创建和管理问题。通过将工厂类设计为单例,我们可以确保全局共享的工厂实例,同时通过工厂模式灵活创建不同类型的对象。这种组合在实际开发中非常实用,特别是在需要集中管理全局资源(如数据库连接、日志系统、配置管理器)时尤为适合。

相关推荐
ChinaRainbowSea8 分钟前
三. Redis 基本指令(Redis 快速入门-03)
java·数据库·redis·缓存·bootstrap·nosql
DEARM LINER8 分钟前
RabbitMQ 分布式高可用
java·spring boot·分布式·rabbitmq
weisian15115 分钟前
消息队列篇--扩展篇--码表及编码解码(理解字符字节和二进制,了解ASCII和Unicode,了解UTF-8和UTF-16,了解字符和二进制等具体转化过程等)
java·开发语言
呦呦鹿鸣Rzh22 分钟前
实现标题-超链接
java·前端·javascript
Bug退退退12329 分钟前
JVM常见知识点
java·jvm
Tester_孙大壮41 分钟前
第31章 测试驱动开发中的设计模式与重构解析(Python 版)
python·设计模式·重构
fly spider1 小时前
每日 Java 面试题分享【第 13 天】
java·开发语言·面试
大名顶顶1 小时前
【JAVA实战】如何使用 Apache POI 在 Java 中写入 Excel 文件
java·spring boot·后端·计算机·程序员·编程·软件开发
gentle_ice2 小时前
leetcode——矩阵置零(java)
java·算法·leetcode·矩阵