单例模式

单例模式

定义

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

使用场景

确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象应该有且只有一个。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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值