美文网首页
学习笔记:设计模式之单例模式

学习笔记:设计模式之单例模式

作者: 大力papa | 来源:发表于2020-08-12 11:53 被阅读0次

本文仅供学习交流使用,侵权必删。
不作商业用途,转载请注明出处。

WHAT 什么是单例

image.png

如果一个类只允许创建一个对象或者实例,那么这个类就是一个单例类。这种方式就是单例设计模式。

单例存在的问题

  • 单例违背面向对象的抽象特性。单例的实现并非基于接口而非实现的设计原则
  • 单例违背面向对象的继承特性。因为构造函数已经私有化,子类无法通过super关键字来调用父构造方法

WHY 为什么使用单例

单例的存在能够提高对象的复用性,减少内存资源不必要的占用。某些业务场景下,我们需要某个组件是单独存在的。例如id生成器,我们希望只有一个实例生产id。如果存在多个id生成器实例,可能会存在id重复问题。

HOW 单例如何实现

饿汉式

将单例提前初始化,不存在线程安全问题。但提前占用内存资源,不能做到使用的时候才进行实例化。不支持延迟加载

public class Singleton {

    private final static Singleton instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }


    public void execute() {
       // todo
    }
}

懒汉式

使用synchronized保证了线程安全的问题,支持延迟加载。但因为锁粒度较大,每次有线程访问都需要锁的话,会造成一定的性能影响

public class Singleton {

    private Singleton() {
    }

    private static Singleton instance;


    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }


    private void execute(){
        // todo
    }

}

双重检测

双重校验:支持延迟加载,锁的粒度比懒汉式小,不会每次获取实例都需要加锁。此外单例需要使用volatile修饰,防止指令重排序导致调用方获取到未初始化完成的对象。

public class Singleton {

    private Singleton() {
    }

    private static volatile Singleton instance = null;


    public static Singleton getInstance() {

        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }



    public void execute() {
         // todo
    }
}

静态内部类

利用JVM类加载机制,内部静态类Holder只有被访问时才会被创建实例对象,只有Holder的实例对象被创建,静态instance才会被创建。通过调用getInstance方法控制Holder类的实例化,从而既能保证线程安全,又能支持延迟加载。

public class Singleton {

    private Singleton() {
    }

    private static class InstanceHolder {
        private final static Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return InstanceHolder.instance;
    }


    public voidexecute() {
        //todo
    }
}

枚举

利用JAVA枚举类型的特性,保证了线程安全和实例唯一。枚举能保证无法通过反射和序列化方式破解单例模式,能做到真正的单例。

public enum Singleton {

    INSTANCE;

    public void execute() {
        //todo
    }
}

持续更新...

相关文章

网友评论

      本文标题:学习笔记:设计模式之单例模式

      本文链接:https://www.haomeiwen.com/subject/kofydktx.html