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

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

相关推荐
鸠。9 分钟前
Java基础复习(JavaSE进阶)第八章 多线程
java·开发语言
AEMC马广川13 分钟前
关于综合能源服务认证证书的全解析专业认证团队
java·大数据·服务器·能源
菜就多练吧1 小时前
JVM 内存分布详解
java·开发语言·jvm
A.lways2 小时前
【软考-系统架构设计师】设计模式三大类型解析
设计模式·系统架构
0白露2 小时前
设计模式之工厂方法模式
java·python·设计模式·php·工厂方法模式
triticale2 小时前
【数论】快速幂
java·算法
爱的叹息3 小时前
【java实现+4种变体完整例子】排序算法中【计数排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
java·算法·排序算法
aiden:)5 小时前
网上图书销售系统 UML 状态图解析:触发器事件、动作与监视条件
设计模式·软件工程·软件构建·uml
刘卜卜&嵌入式5 小时前
C++_设计模式_观察者模式(Observer Pattern)
c++·观察者模式·设计模式