设计模式-单例模式

大憨熊 提交于 2020-01-15 04:03:03

对某个类只能存在一个对象实例,并且该类只提供一个获得其对象实例的方法(静态方法)

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

饿汉式(静态变量)

public class Singleton1 {
  public static void main(String[] args) {
      //测试
      Singleton instance1=Singleton.getInstance();
      Singleton instance2=Singleton.getInstance();
      System.out.println(instance1==instance2);//true
  }
}


//饿汉式(静态常量)
class Singleton{

  //1.构造器私有化,外部不能new
  private Singleton(){

  }

  //2.本类内部创建对象实例
  private final static Singleton instance=new Singleton();

  //3.提供一个公有的静态方法,返回实例对象
  public static Singleton getInstance(){
      return instance;
  }
}

优缺点:
1.优点:写法简单,在类装载的时候就完成实例化。避免了线程同步问题
2.缺点:没有达到Lazy Loading(懒加载)的效果:如果从始到终没有用到这个实例就会产生内存浪费。
3.这种方式基于类加载机制避免了多线程的同步问题,但instance在类装载时就实例化,在单例模式中大多数都是调用getInstance方法,但是导致类加载的原因有很多,可能不是使用getInstance却导致类加载,导致没有实现懒加载,造成内存浪费

饿汉式(静态代码块)

public class Singleton2 {
    public static void main(String[] args) {
        //测试
        Singleton instance1=Singleton.getInstance();
        Singleton instance2=Singleton.getInstance();
        System.out.println(instance1==instance2);//true
    }
}

//饿汉式(静态代码)
class Singleton{

    //1.构造器私有化,外部不能new
    private Singleton(){

    }

    //2.本类静态变量
    private static Singleton instance;

    //3.在静态代码块中创建单例对象
    static{
        instance=new Singleton();
    }

    //4.提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance(){
        return instance;
    }
}

优缺点:
1.优缺点跟饿汉式(静态常量)一样

懒汉式(线程不安全)

public class Singleton3 {
    public static void main(String[] args) {
        //测试
        Singleton instance1=Singleton.getInstance();
        Singleton instance2=Singleton.getInstance();
        System.out.println(instance1==instance2);//true
    }
}

//懒汉式(线程不安全)
class Singleton{

    //1.构造器私有化,外部不能new
    private Singleton(){

    }

    private static Singleton instance;

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

}

优缺点:
1.实现懒加载,但只能在单线程的时候使用。
2.线程不安全的原因:再多线程下,一个线程进入到if(instance==null)判断语句块,还未执行下去,其他线程也通过了这个判断语句,这时便会产生多实例。

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

public class Singleton4 {
    public static void main(String[] args) {
        //测试
        Singleton instance1=Singleton.getInstance();
        Singleton instance2=Singleton.getInstance();
        System.out.println(instance1==instance2);//true
    }
}

//懒汉式(线程安全,同步方法)
class Singleton{

    private Singleton(){

    }

    private static Singleton instance;

    //提供一个静态的公有方法,当使用到该方法时,才去创建instance对象
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }

}

优缺点:
1.解决了线程不安全的问题
2.效率太低了,每个类想要获取实例都需要执行getInstance()同步,而其实这方法只需要一次实例化,其他方法直接return就可以。方法同步效率太低

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

垃圾,不用学

双重检查

public class Singleton6 {
    public static void main(String[] args) {
        //测试
        Singleton instance1=Singleton.getInstance();
        Singleton instance2=Singleton.getInstance();
        System.out.println(instance1==instance2);//true
    }
}


class Singleton{

    private Singleton(){

    }

    private static volatile Singleton instance;//volatile:修改值立即更新到主存

    //加入双重检查,解决线程安全问题,同时解决懒加载问题
    public static Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}  }
}

优缺点:
1.Double-Check概念再多线程中常用,进行两次if(instance==null)检查,保证线程安全。
2.实例化代码只执行一次,避免反复进行方法同步。
3.线程安全、懒加载;效率较高。

静态内部类

public class Singleton7 {
    public static void main(String[] args) {
        //测试
        Singleton instance1=Singleton.getInstance();
        Singleton instance2=Singleton.getInstance();
        System.out.println(instance1==instance2);//true
    }
}

//静态内部类
//静态内部类特点:1.外部类装置的时候,内部静态类不会被装载 2.内部调用的时候,静态内部类只会执行一次
class Singleton{
    private Singleton(){

    }

    //静态内部类,该类中有一个静态属性Singleton
    //JVM处理类加载的时候是线程安全的
    public static class SingletonInstance{
        private static final Singleton instance=new Singleton();
    }

    //提供一个静态公有方法,直接返回SingletonInstance.instance
    public static Singleton getInstance(){
        return SingletonInstance.instance;
    }

}

优缺点:
1.采用类加载机制来保证初始化实例的时候只有一个线程。
2.静态内部方法在Singleton类被装载时,不会立即实例化,调用getInstance时才会实例化。
3.类的静态属性只会在第一次加载的时候进行初始化。
4.线程安全、懒加载、效率高。

枚举

public class Singleton8 {
    public static void main(String[] args) {
        //测试
        Singleton instance1=Singleton.INSTANCE;
        Singleton instance2=Singleton.INSTANCE;
        System.out.println(instance1==instance2);//true
    }
}

//枚举
enum Singleton{
    INSTANCE;
    public void sayOK(){
        System.out.println("ok");
    }
}

优缺点:
1.借助JDK1.5中添加的枚举类实现单例模式,不仅能避免多线程同步问题,而且还能防止反序列化重新创建对象。
2.Java作者推荐方式。

本文为本人的尚硅谷教程的笔记
视频地址:https://www.bilibili.com/video/av57936239

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!