美文网首页
单例模式 学习

单例模式 学习

作者: fdsun | 来源:发表于2021-01-20 12:27 被阅读0次

单例模式

单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
隐藏其所有的构造方法。
属于创建型模式。

适用场景:

确保任何情况下都绝对只有一个实例。

单例模式的优点:

在内存中只有一个实例,减少了内存开销。
可以避免对资源的多重占用。
设置全局访问点,严格控制访问。

单例模式的缺点:

没有接口,扩展困难。
如果要扩展单例对象,只有修改代码,没有其他途径。

单例模式的常见写法:

1、饿汉式单例
2、懒汉式单例
3、注册式单例
4、ThreadLocal单例

饿汉式单例:

在单例类首次加载时就创建实例
缺点:浪费内存空间

饿汉式单例
public class HungrySingleton {
    private static final HungrySingleton hungrySingleton = new HungrySingleton();
    private HungrySingleton() {
    }
    public static HungrySingleton getInstance() {
        return hungrySingleton;
    }
}
/**
 * 饿汉式静态块单例
 */
public class HungryStaticSingleton {
    private static final HungryStaticSingleton hungrySingleton;
        static {
        hungrySingleton = new HungryStaticSingleton();
    }
    private HungryStaticSingleton() {
    }
    public static HungryStaticSingleton getInstance() {
        return hungrySingleton;
    }
}

懒汉式单例:

被外部类调用时才创建实例

懒汉式单例
public class LazySimpleSingleton {
    private LazySimpleSingleton() {
    }
    private static LazySimpleSingleton lazy = null;
    // 存在性能问题  -> DoubleCheck
    public synchronized static LazySimpleSingleton getInstance() {
        if (lazy == null) {
            lazy = new LazySimpleSingleton();
        }
        return lazy;
    }
}
public class LazyDoubleCheckSingleton {
    private volatile static LazyDoubleCheckSingleton lazy = null;

    private LazyDoubleCheckSingleton() {
    }
    // 适中的方案
    // 双重检查锁
    public static LazyDoubleCheckSingleton getInstance() {
        if (lazy == null) {
            synchronized (LazyDoubleCheckSingleton.class) {
                if (lazy == null) {
                    lazy = new LazyDoubleCheckSingleton();
                    //  cpu执行时候会转换成JVM指令执行
                    // 指令重排序的问题, volatile
                    //1.分配内存给这个对象
                    //2.初始化对象
                    //3.设置lazy指向刚分配的内存地址
                    //4.初次访问对象
                }
            }
        }
        return lazy;
    }
}
/**
 * 懒汉式单例
 * 这种形式兼顾饿汉式的内存浪费,也兼顾synchronized性能问题
 * 完美地屏蔽了这两个缺点
 * <p>
 * 全程没有用到synchronized
 * 性能最优的一种写法
 */
public class LazyInnerClassSingleton {
        private LazyInnerClassSingleton() {
        // 防止使用反射恶意调用,破坏单例
        if (LazyHolder.LAZY != null) {
            throw new RuntimeException("不允许创建多个实例");
        }
    }

    /**
     * 懒汉式单例
     * LazyHolder 里面的逻辑需要等到外部方法调用时才执行
     * 巧妙利用了内部类的特性
     * JVM底层独行逻辑,完美地避免了线程安全阿题
     */
    public static final LazyInnerClassSingleton getInstance() {
        //在返回结果以前,一定会先加载内部类
        return LazyHolder.LAZY;
    }

    // 默认不加载
    private static class LazyHolder {
        private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
    }
}

注册式单例:

将每一个实例都缓存到统一的容器中,使用唯一标识获取实例

注册式单例
/**
 * 枚举单例
 */
public enum EnumSingleton {
    // 单例
    INSTANCE;
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}
public class ContainerSingleton {
    private ContainerSingleton() {
    }

    private static Map<String, Object> ioc = new ConcurrentHashMap<String, Object>();

    public static Object getInstance(String className) {
        synchronized (ioc) {
            if (!ioc.containsKey(className)) {
                Object obj = null;
                try {
                    obj = Class.forName(className).newInstance();
                    ioc.put(className, obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return obj;
            } else {
                return ioc.get(className);
            }
        }
    }
}

ThreadLocal单例:

保证线程内部的全局唯一,且天生线程安全

ThreadLocal单例
public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> THREAD_LOCAL_INSTANCE =
            ThreadLocal.withInitial(ThreadLocalSingleton::new);

    private ThreadLocalSingleton() {
    }

    public static ThreadLocalSingleton getInstance() {
        return THREAD_LOCAL_INSTANCE.get();
    }
}

学习单例模式的知识重点总结:

1、私有化构造器
2、保证线程安全
3、延迟加载
4、防止序列化和反序列化破坏单例
5、防御反射攻击单例

相关文章

  • 设计模式系列教程之单例模式-原理介绍

    设计模式系列教程之单例模式-原理介绍 一:单例模式(Singleton)学习步骤 经典的单例模式原理: 本文出处:...

  • iOS-单例模式

    swift的单例设计模式 OC的单例设计模式 新学习一种单例思想

  • 【设计模式】单例模式

    学习文章 iOS设计模式 - 单例 SwiftSingleton 原理图 说明 单例模式人人用过,严格的单例模式很...

  • python 单例

    仅用学习参考 目标 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计...

  • 设计模式之单例模式

    单例设计模式全解析 在学习设计模式时,单例设计模式应该是学习的第一个设计模式,单例设计模式也是“公认”最简单的设计...

  • Android 单例模式学习

    android的单例模式学习 1 饿汉单例模式 优点 : 缺点 : 2.0 懒汉模式 优点 : 缺点 : 2.1 ...

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: Android Application 中使用单例模式:

  • Android设计模式总结

    单例模式:饿汉单例模式://饿汉单例模式 懒汉单例模式: Double CheckLock(DCL)实现单例 Bu...

  • JAVA中各种单例模式的实现与分析

    单例模式是学习设计模式过程中最基本的一个设计模式,基本上一开始学习就会学到单例模式,实际上在java中实现单例模式...

  • 初识设计模式之单例模式

    此文为笔者个人的学习笔记,在学习部分博客、书籍、资料后所总结,仅供参考。 对单例模式的认识单例模式是什么单例模式的...

网友评论

      本文标题:单例模式 学习

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