妙解设计模式之单例模式

目录

单例模式的概念

单例模式(Singleton Pattern)是一种设计模式,用于确保一个类在整个程序运行过程中只有一个实例,并提供一个全局访问点来获取该实例。这种模式在需要控制资源使用(如数据库连接、文件访问)或者需要全局共享状态的场景中非常有用。

单例模式的具体概念

  1. 唯一实例
    • 单例模式确保一个类只有一个实例存在。任何时候,任何地方访问这个类时,都能获得相同的实例。这就避免了多个实例带来的资源浪费和状态不一致问题。
  2. 全局访问点
    • 单例模式提供一个全局访问点,可以通过这个访问点获取唯一的实例。通常是通过一个静态方法来实现。

单例模式的实现要点

  1. 私有构造函数
    • 将类的构造函数定义为私有,防止外部类直接通过new关键字创建多个实例。
  2. 静态变量
    • 使用一个私有的静态变量来保存类的唯一实例。
  3. 静态方法
    • 提供一个公共的静态方法,用于返回唯一的实例。在这个方法中,通常会检查实例是否已经存在,如果不存在则创建新的实例,如果存在则直接返回。

生活中的例子

单例模式,用来确保一个类只有一个实例,并且提供一个全局访问点来访问这个实例。想象一下你家里的冰箱。

  1. 冰箱只有一个:家里通常只有一个冰箱,不需要多个冰箱来储存食物。单例模式就像这个冰箱,确保只有一个实例存在。

  2. 全家人都能用:家里所有人都可以打开冰箱拿食物。单例模式也一样,程序中的所有部分都可以访问这个唯一的实例。

编程中的例子

下面是用Java实现单例模式的例子。我们来创建一个名为Singleton的类,确保这个类只能有一个实例,并且全局可访问。

java 复制代码
public class Singleton {
    // 私有静态实例变量,用来存储唯一的实例
    private static Singleton instance;

    // 私有化构造函数,防止外部类创建实例
    private Singleton() {}

    // 公共的静态方法,返回唯一的实例
    public static Singleton getInstance() {
        // 第一次调用时创建实例,以后调用直接返回现有实例
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    // 其他方法
    public void showMessage() {
        System.out.println("Hello, I am a Singleton!");
    }
}

class Main {
    public static void main(String[] args) {
        // 尝试获取Singleton实例
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        // 比较两个实例,看看它们是否是同一个
        System.out.println(singleton1 == singleton2); // 这会打印 true

        // 调用实例的方法
        singleton1.showMessage(); // 这会打印 "Hello, I am a Singleton!"
    }
}

软件工程中的实际应用

配置管理

场景

  • 在一个大型应用程序中,配置参数可能需要被多个模块访问和修改。

实践

  • 使用单例模式确保配置管理类只有一个实例,从而保证所有模块访问的都是同一个配置实例,避免配置不一致的问题。
java 复制代码
public class ConfigurationManager {
    private static ConfigurationManager instance;
    private Properties configProperties;

    private ConfigurationManager() {
        configProperties = new Properties();
        // 加载配置文件
        // configProperties.load(...);
    }

    public static synchronized ConfigurationManager getInstance() {
        if (instance == null) {
            instance = new ConfigurationManager();
        }
        return instance;
    }

    public String getProperty(String key) {
        return configProperties.getProperty(key);
    }

    public void setProperty(String key, String value) {
        configProperties.setProperty(key, value);
    }
}

日志管理

场景

  • 应用程序需要记录日志,并且这些日志信息需要集中管理和输出。

实践

  • 使用单例模式确保日志管理类只有一个实例,所有日志记录都通过这个实例进行处理,避免多个日志实例造成的混乱。
java 复制代码
public class Logger {
    private static Logger instance;

    private Logger() {
        // 初始化日志配置
    }

    public static Logger getInstance() {
        if (instance == null) {
            instance = new Logger();
        }
        return instance;
    }

    public void log(String message) {
        // 记录日志信息
        System.out.println(message);
    }
}

数据库连接池

场景

  • 数据库连接是昂贵的资源,频繁创建和销毁连接会导致性能问题。

实践

  • 使用单例模式创建数据库连接池,确保全局只有一个连接池实例,从而管理和复用数据库连接,提升性能。
java 复制代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DatabaseConnectionPool {
    private static DatabaseConnectionPool instance;
    private List<Connection> connectionPool;

    private DatabaseConnectionPool() {
        connectionPool = new ArrayList<>();
        // 初始化连接池
        for (int i = 0; i < 10; i++) {
            connectionPool.add(createNewConnection());
        }
    }

    public static DatabaseConnectionPool getInstance() {
        if (instance == null) {
            instance = new DatabaseConnectionPool();
        }
        return instance;
    }

    private Connection createNewConnection() {
        try {
            return DriverManager.getConnection("jdbc:yourdatabaseurl", "user", "password");
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    public Connection getConnection() {
        if (connectionPool.isEmpty()) {
            return createNewConnection();
        } else {
            return connectionPool.remove(connectionPool.size() - 1);
        }
    }

    public void releaseConnection(Connection connection) {
        connectionPool.add(connection);
    }
}

缓存管理

场景

  • 在应用程序中,某些数据需要频繁访问,但计算或获取这些数据的成本很高。

实践

  • 使用单例模式创建一个缓存管理类,确保全局只有一个缓存实例,从而共享缓存数据,提升访问速度。
java 复制代码
import java.util.HashMap;
import java.util.Map;

public class CacheManager {
    private static CacheManager instance;
    private Map<String, Object> cache;

    private CacheManager() {
        cache = new HashMap<>();
    }

    public static CacheManager getInstance() {
        if (instance == null) {
            instance = new CacheManager();
        }
        return instance;
    }

    public void put(String key, Object value) {
        cache.put(key, value);
    }

    public Object get(String key) {
        return cache.get(key);
    }

    public void remove(String key) {
        cache.remove(key);
    }
}

线程池管理

场景

  • 在并发编程中,创建和销毁线程是开销很大的操作。

实践

  • 使用单例模式创建一个线程池管理类,确保全局只有一个线程池实例,从而管理和复用线程,提升并发性能。
java 复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolManager {
    private static ThreadPoolManager instance;
    private ExecutorService executorService;

    private ThreadPoolManager() {
        executorService = Executors.newFixedThreadPool(10);
    }

    public static ThreadPoolManager getInstance() {
        if (instance == null) {
            instance = new ThreadPoolManager();
        }
        return instance;
    }

    public void execute(Runnable task) {
        executorService.execute(task);
    }

    public void shutdown() {
        executorService.shutdown();
    }
}
相关推荐
zaim135 分钟前
计算机的错误计算(一百一十四)
java·c++·python·rust·go·c·多项式
hong_zc2 小时前
算法【Java】—— 二叉树的深搜
java·算法
进击的女IT3 小时前
SpringBoot上传图片实现本地存储以及实现直接上传阿里云OSS
java·spring boot·后端
Miqiuha3 小时前
lock_guard和unique_lock学习总结
java·数据库·学习
一 乐4 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
数云界4 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
阑梦清川4 小时前
Java继承、final/protected说明、super/this辨析
java·开发语言
GISer_Jing4 小时前
【React】增量传输与渲染
前端·javascript·面试
快乐就好ya6 小时前
Java多线程
java·开发语言
IT学长编程6 小时前
计算机毕业设计 二手图书交易系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·二手图书交易系统