设计模式学习笔记-单例模式

介绍

单例模式就是采取一定方法保证整个软件系统中,对某个类只能存在一个对象实例,并且该类只能提供一个取得其对象的方法,一般为静态方法。

单例模式的实现方式

  1. 饿汉式(静态常量)
  2. 饿汉式(静态代码块)
  3. 懒汉式(线程不安全)
  4. 懒汉式(线程安全,同步方法)
  5. 懒汉式(线程安全,同步代码块)
  6. 双重检查
  7. 静态内部类
  8. 枚举

饿汉式(静态常量)

实现步骤

  • 构造器私有化
  • 类的内部创建对象
  • 向外暴露一个公共静态方法

代码实现

class Singleton{
    //构造器私有化
    private Singleton(){
    }
    //本类内部创建对象实例
    private final static Singleton instance = new Singleton();
    //提供公共方法
    public static Singleton getInstance(){
        return instance;
    }
}

优缺点

  1. 类加载时即完成初始化避免多线程同步问题
  2. 没有懒加载的效果,若此类一直未被使用造成空间浪费

饿汉式(静态代码块)

class Singleton{
    //构造器私有化
    private Singleton(){
    }
    private final static Singleton instance;
    //静态代码块中创建对象
    static{
       instance = new Singleton();
    }
    //提供公共方法
    public static Singleton getInstance(){
        return instance;
    }
}

优缺点: 和上边一样

懒汉式(线程不安全)

class Singleton{
    private static Singleton instance;
    //构造器私有化
    private Singleton(){ }
    public static Singleton getInstance(){
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }
}

懒汉式(线程安全,同步方法)

class Singleton{
    private static Singleton instance;
    //构造器私有化
    private Singleton(){ }
    //加锁
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }
}

缺点: 效率太低

懒汉式(线程安全,同步代码块)

class Singleton{
    private static Singleton instance;
    //构造器私有化
    private Singleton(){ }
    public static Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                instance = new Singleton();instance = new Singleton();
            }
        }
        return instance;
    }
}

存在问题: 当有多个线程判断instance为空进入if代码块后会创建多个实例

双重检查

推荐使用

class Singleton{
    //注意加volatile
    private static volatile Singleton instance;
    //构造器私有化
    private Singleton(){ }
    public static Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                if(instance==null){
                    instance = new Singleton();instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

注意: volatile关键字为了防止指令重排,一般new对象时分为三步
1.分配内存空间
2.初始化对象
3.把引用变量指向这个地址
因为JVM有可能在不影响结果的情况下进行相关的指令重排操作比如上述顺序变为1,3,2这样当进行第一个if判断时有可能是instance先指向了实例对象内存地址但是对象还未进行初始化此时返回instance的话会造成错误。

优点: 既实现了懒加载又保证了线程安全。

静态内部类

推荐使用

class Singleton{
    //构造器私有化
    private Singleton(){ }
    //静态内部类
    private static class SingletonInstance{
        private static final Singleton INSTANCE = new Singleton();
    } 
    public static Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}

注意: 静态内部类在外部类加载时不会加载,当使用到静态内部类时才会加载,另外在加载过程中是线程安全的,这样也保证了懒加载和线程安全。

枚举

推荐使用

enum  Singleton{
    INSTANCE;
    public void fun(){
        //balabala
    }
}

优点: 避免线程同步问题,还能防止反序列化重新创造对象

单例模式的应用

Runtime类使用了饿汉式
设计模式学习笔记-单例模式_第1张图片

单例模式细节说明

  1. 单例模式保证了获取类实例时只能获取相同对象。
  2. 主要用于工具类对象,频繁访问数据库对象等频繁使用的对象

你可能感兴趣的:(设计模式)