单例模式

    xiaoxiao2021-04-17  44

    单例模式

    定义

    确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

    使用场景

    确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象应该有且只有一个。Android常通过context.getSystemService()获取,系统核心服务以单例模式存在,减少了资源消耗

    实现

    实现单例的注意事项: 1. 构造函数不对外开放(private) 2. 通过一个静态方法或者枚举返回单例对象 3. 确保任何时候单例类的对象有且只有一个(eg:多线程) 4. 确保单例类对象在反序列化时不会重新构建对象 使用时,通过静态方法获取到单例类的唯一对象

    饿汉模式

    利用静态成员会在类初始化时自行创建来保证只有一个实例

    public class Singleton{ private static final Singleton instance=new Singleton(); //构造函数私有 private Singleton(){ } public static Singleton getInstance(){ return instance; } }

    由于instance是静态变量,在类初始化时就会创建并存留在堆中(Java7 之前,常量池的存储在方法区;Java7 及 Java8,将常量池的存储转移到了 堆。但不管怎样,使用new操作符产生的对象实例存储在堆中) 这样确保了单例类实例只会创建一次。(初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器)

    懒汉模式

    在首次调用获取实例的方法时创建对象

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

    优点:

    只在使用时才会实例化,节约资源

    缺点:

    第一次加载时及时进行实例化反应稍慢每次调用getInstance()都进行同步,造成不必要的同步开销

    双重锁模式(DCL)

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

    优点:

    只在使用时才会实例化,节约资源相比懒汉式单例,避免了不必要的同步

    缺点:

    第一次加载时及时进行实例化反应稍慢

    静态内部类实现

    public class Singleton{ private Singleton(){ } public static Singleton getInstance(){ return SingletonHolder.instance; } //静态内部类 public static class SingletonHolder{ private static final Singleton instance = new Singleton(); } }

    利用静态内部类只在静态内部类首次调用才初始化的性质

    枚举单例

    public enum SingletonEnum{ INSTANCE; }

    优点

    代码简单默认枚举实例的创建在Java中是线程安全的

    容器实现单例模式

    public class SinlgetonManager{ private static Map<String,Object> objMap = new HashMap<String,Object>(); private SinlgetonManager(){ } public static void registerService(String key,Object instance){ if(!objMap.containsKey(key)){ objMap.put(key,instance); } } public static Object getService(String key){ return objMap.get(key); } }

    将多种单例类型注入到一个统一的管理类中,在使用时根据key获取对象对应类型的对象

    总结

    优点

    减少了内存开支,特别是某个对象需要频繁创建时减少系统性能开销,特别是创建对象需要比较长时间时 避免了对一些资源的多重占用设置全局的访问点,可以优化和共享资源访问

    缺点

    一般单例模式没有接口,扩展很困难内存泄漏: 单例对象如果持有Context,很容易引发内存泄漏,因此尽量使用生命周期最长的ApplicationContext
    转载请注明原文地址: https://ju.6miu.com/read-673834.html

    最新回复(0)