单例模式

来源:互联网 发布:nginx if break 编辑:程序博客网 时间:2024/06/07 20:52

单例模式

定义

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

使用场景

确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象应该有且只有一个。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
原创粉丝点击