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. 总结

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

相关推荐
WeiLai111243 分钟前
面试基础--Redis 缓存穿透、缓存击穿、缓存雪崩深度解析
java·redis·分布式·后端·缓存·面试·架构
zctel44 分钟前
java中小型公司面试预习资料(二):Redis
java·redis·面试
爱吃烤鸡翅的酸菜鱼2 小时前
Java【网络原理】(3)网络编程续
java·运维·服务器·网络
╰つ゛木槿5 小时前
Spring Boot 调用DeepSeek API的详细教程
java·spring boot·后端·deepseek
hhw1991126 小时前
c#面试题整理6
java·开发语言·c#
程序视点7 小时前
SpringBoot配置入门
java·spring boot·spring
Benaso8 小时前
Java,Golang,Rust 泛型的大体对比小记
java·golang·rust
程序员清风8 小时前
什么时候会考虑用联合索引?如果只有一个条件查就没有建联合索引的必要了么?
java·后端·面试
Seven978 小时前
【设计模式】掌握建造者模式:如何优雅地解决复杂对象创建难题?
java·后端·设计模式
自在如风。8 小时前
MyBatis-Plus 使用技巧
java·mybatis·mybatis-plus