设计模式——单例模式

70 阅读4分钟

设计模式——单例模式

所谓类的单例设计模式,就是采用一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

饿汉式(静态常量)

1.构造器私有化(防止 new)

2.类的内部创建对象

3.向外暴露一个静态公共方法,getInstance

//饿汉式(静态变量)
//写法简单,类加载时就完成了实例化
//如果从始至终未使用过这个实例,可能造成内存浪费

class Singleton{
    //1.构造器私有化,外部不能new
    private Singleton(){
        
    }
    //2.本类内部创建对象实例
    private final static Singleton instance = new Singleton();
    
    //3.提供一个公有的静态方法,返回对象实例
    public static Singleton getInstance(){
        return instance;
    }
}

饿汉式(静态代码块)

//饿汉式(静态代码块)
//写法简单,类加载时就完成了实例化
//如果从始至终未使用过这个实例,可能造成内存浪费

class Singleton{
    //1.构造器私有化,外部不能new
    private Singleton(){
        
    }
    //2.本类内部创建对象实例
    private  static Singleton instance;
    
    static{
        //在静态代码块中创建单例对象
        instance = new Singleton();
    }
    //3.提供一个公有的静态方法,返回对象实例
    public static Singleton getInstance(){
        return instance;
    }
}

懒汉式(线程不安全)

1.起到了懒加载的效果,但是只能在单线程下使用

2.如果在多线程下,一个线程进入到if(singleton==null)语句,还未来得及向下执行,另一个线程也通过了这种判断语句,这时候便会产生多个实例,所以在多线程下不可以使用这种方式

3.在实际开发中不要使用

class Singleton{
    private static Singleton instance;
    private Singleton(){}
    
    //提供一个静态的公有方法,当使用到该方法时才创建instance
    //即懒汉式
    public static Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

懒汉式(线程安全)

1.解决了线程不安全问题

2.效率低,每个线程在想获得类的实例时候,执行getinstance()方法都要进行同步,而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就可以了,方法进行同步效率低

3.在实际开发中不推荐使用

class Singleton{
    private static Singleton instance;
    private Singleton(){}
    
    //提供一个静态的公有方法,当使用到该方法时才创建instance
    //即懒汉式
    //线程安全(加入了synchronized),解决线程安全问题
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

双重检查

1.double-check在多线程开发中经常使用,保证线程安全

2.实例化代码只用执行一次,线程安全,延迟加载,效率较高

3.推荐使用

class Singleton{
    private static volatile Singleton instance;
    private Singleton(){}
    
    //提供一个静态的公有方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题
    //同时保证效率,推荐使用
    public static  Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                if(instance ==null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

单例模式(静态内部类)

1.采用类装载机制来保证初始化实例时只有一个线程(JVM底层原理)

2.静态内部类方式在Singleton类被装载时并不会立刻实例化,而是在需要实例化时调用getInstance方法,才会装在对应的SingletonInstance类,从而完成Singleton的实例化

3.类的静态属性只会在第一次加载类时初始化,JVM帮我们保证了线程安全性,类初始化时其他线程无法进入

4.推荐使用

class Singleton{
    private static  Singleton instance;
    private Singleton(){}
    
    //写一个静态内部类,该类中有一个静态属性Singleton
    private static class SingletonInstance{
        
        private static final Singleton INSTANCE = new Singleton();
    }
    //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
    public static  Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}

单例模式(枚举)

1.不仅能够避免多线程同步问题,而且还能防止反序列化重新创建新的对象

2.推荐使用

//使用枚举可以实现单例,推荐使用
enum Singleton{
    INSTANCE;
    public void sayOK(){
        System.out.println("ok");
    }
}

TIPS:

1.单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例方式可以提高系统性能

2.当想实例化一个单例类时,必须要使用相应的获取对象的方法,而不是使用new