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

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

作者: 大力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