01-单例模式

54 阅读2分钟

什么是单例模式

单例模式是一种常用的软件设计模式,所谓单例就是所有的请求都用一个对象来处理。通过单例模式可以保证系统中只有一个该类的实例对象,而且该实例用于外界访问使用。

使用场景

单例模式通常使用在需要控制资源访问配置管理日志记录器等情况下.

实现方式

方式一(懒汉式)

// 单例实例demo  
// 懒汉式  
public class SingleInstance {  
    // 声明一个私有静态变量来保存单例实例  
    private static SingleInstance singleInstance;  
  
    // 私有构造方法,防止外部创建实例  
    private SingleInstance() {  
    }  
    /**  
     * 获取单例实例  
     * synchronized:添加线程同步锁,防止多线程情况下创建多个实例,确保只有一个实例,但是速度会变慢,会有性能损失  
     *               不考虑性能的情况下,可以使用synchronized加锁的方式来实现单例模式  
     * @return 单例实例  
     */  
    public synchronized static SingleInstance getInstance() {  
        if (singleInstance == null) {  
            singleInstance = new SingleInstance();  
        }  
        return singleInstance;  
    }  
}

方式二(饿汉式)

类加载的初始化阶段就完成了实例的初始化。 本质上是借助jvm类的加载机制保证实例的唯一性

// 单例实例demo  
// 饿汉式  
public class SingleInstance {  
    // 声明一个私有静态变量来保存单例实例  
    private static SingleInstance singleInstance = new SingleInstance();  
  
    // 私有构造方法,防止外部创建实例  
    private SingleInstance() {  
    }  
    /**  
     * 获取单例实例  
     * @return 单例实例  
     */  
    public static SingleInstance getInstance() {  
        return singleInstance;  
    }  
}

方式三(匿名内部类)

本质上是利用类的加载机制来保证线程安全, 只有在实际使用的时候,才会对实例进行初始化,也是懒汉模式的一种形式

// 单例实例demo  
// 匿名内部类实现单例模式  
public class SingleInstance {  
    // 私有构造方法,防止外部创建实例  
    private SingleInstance() {  
    }  
    // 静态内部类,延迟加载,调用时才创建  
    private static class SingleInstanceHolder {  
        private static final SingleInstance INSTANCE = new SingleInstance();  
    }  
  
    // 获取实例  
    public static SingleInstance getInstance() {  
        return SingleInstanceHolder.INSTANCE; // 返回静态内部类的实例,在第一次调用时才创建  
    }  
}

问题

  • 在以上三种方式下可以通过反射来创建多个实例对象 解决方法: 1、在懒汉式情况下可以通过在构造方法内判断是否已经存在实例化对象来防止通过反射创建多个实例 2、
// 方式一中构造方法改造 
private SingleInstance() {  
    // 防止反射创建实例  
    if (singleInstance != null) {  
        throw new RuntimeException("单例模式不允许多个实例");  
    }  
}

// 方式三中构造方法改造
private SingleInstance() {  
    // 防止反射创建实例  
    if (SingleInstanceHolder.INSTANCE != null) {  
        throw new RuntimeException("单例模式不允许创建多个实例");  
    }  
}

扩展

单例序列化