Java中的单例模式是一种常见的设计模式,它用于确保类只有一个实例,并提供全局的访问点。在某些场景下,单例模式可以提高系统的性能和效率。下面是单例模式详解的完整攻略:
什么是单例模式
单例模式(Singleton Pattern)是一种常见的创建型设计模式,它可以确保一个类只有一个实例,并提供全局的访问点。单例模式可以避免不必要的对象创建,提高系统的性能和效率。此外,在一个多线程的环境下,单例模式还可以避免竞态条件和锁竞争。
单例模式的实现
单例模式的实现一般有两种方法:饿汉式和懒汉式。
饿汉式
饿汉式是一种较为简单的单例模式实现方式,它的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。常见的实现方式如下:
public class Singleton {
// 在类加载的时候就创建单例对象
private static Singleton instance = new Singleton();
// 私有构造函数,确保外部无法实例化该类
private Singleton() {}
// 获取单例的唯一访问点
public static Singleton getInstance() {
return instance;
}
}
懒汉式
懒汉式是一种比较懒惰的单例模式实现方式,它的特点是单例的实例只会在第一次调用 getInstance 方法时被创建。常见的实现方式如下:
public class Singleton {
// 声明单例,但暂时不创建单例对象
private static Singleton instance = null;
// 私有构造函数,确保外部无法实例化该类
private Singleton() {}
// 获取单例的唯一访问点
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重校验锁式
双重校验锁式是一种线程安全的懒汉式单例模式实现方式,它的特点是在需要时才会创建单例。通过双重校验锁,既避免了锁竞争,又避免了每次获取锁的开销。常见的实现方式如下:
public class Singleton {
// 声明单例,但暂时不创建单例对象
private static volatile Singleton instance = null;
// 私有构造函数,确保外部无法实例化该类
private Singleton() {}
// 获取单例的唯一访问点
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
单例模式的使用
单例模式在实际开发中经常用于工具类、配置类、日志类等场景中。下面通过两个示例来说明单例模式的使用。
配置文件工具类
我们经常会用到配置文件来保存应用程序的配置信息。下面是一个配置文件工具类的示例,它可以读取和写入配置文件,并提供全局的访问点。
public class ConfigUtil {
// 声明单例,但暂时不创建单例对象
private static volatile ConfigUtil instance = null;
// 保存配置信息的 Map
private Map<String, String> configMap = new HashMap<>();
// 私有构造函数,确保外部无法实例化该类
private ConfigUtil() {
// 初始化配置信息
loadConfig();
}
// 加载配置信息
private void loadConfig() {
// 读取配置文件,将配置信息保存到 configMap 中
}
// 获取单例的唯一访问点
public static ConfigUtil getInstance() {
if (instance == null) {
synchronized(ConfigUtil.class) {
if (instance == null) {
instance = new ConfigUtil();
}
}
}
return instance;
}
// 获取配置信息
public String getConfigValue(String key) {
return configMap.get(key);
}
// 设置配置信息
public void setConfigValue(String key, String value) {
configMap.put(key, value);
}
// 保存配置信息到文件
public void saveConfig() {
// 将 configMap 中的配置信息写入配置文件
}
}
日志记录器
日志记录器通常用于记录应用程序的运行日志。下面是一个简单的日志记录器的示例,它可以记录日志,并提供全局的访问点。
public class Logger {
// 声明单例,但暂时不创建单例对象
private static volatile Logger instance = null;
// 日志文件的路径
private String logFilePath = "";
// 私有构造函数,确保外部无法实例化该类
private Logger() {}
// 获取单例的唯一访问点
public static Logger getInstance() {
if (instance == null) {
synchronized(Logger.class) {
if (instance == null) {
instance = new Logger();
}
}
}
return instance;
}
// 写入日志
public void log(String message) {
// 将日志写入日志文件
}
// 设置日志文件的路径
public void setLogFilePath(String logFilePath) {
this.logFilePath = logFilePath;
}
}
单例模式的扩展
单例模式还可以通过一些扩展方式来增加功能或者优化性能,常见的扩展方式如下:
线程池化单例
线程池化单例是一种将多个单例对象缓存到线程池中,从而提高单例对象的重用率和系统的性能。
延迟加载单例
延迟加载单例是一种将单例对象的创建延迟到第一次使用时再进行,从而避免了不必要的对象创建。
总结
单例模式是一种常见的设计模式,它可以确保一个类只有一个实例,并提供全局的访问点,从而提高系统的性能和效率。单例模式的实现一般有饿汉式、懒汉式和双重校验锁式等方式。在实际开发中,单例模式经常用于工具类、配置类、日志类等场景中。单例模式还可以通过线程池化、延迟加载等方式进行扩展。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的单例模式详解(完整篇) - Python技术站