Android设计模式解析(二)单例模式(Singleton Pattern)
来源:互联网 发布:windows pe.iso镜像 编辑:程序博客网 时间:2024/05/07 10:53
前言
单例显而易见也就是单独、唯一的意思,即一个类只有一个实例,比较简单、常用的一种设计模式
举个栗子
皇帝:
中国有许多的皇帝,一般同一时间段只会有一个皇帝(个别的两个皇帝的就不说了啊),那我们就能认为皇帝就是一个单例模式,在这个场景中,有皇帝、大臣,大臣每天都需要去上朝参见皇帝,今天参见的皇帝和昨天前天参见的皇帝都是一样的。单例模式,绝对的单例模式
使用场景
- 该类占用较多的资源,如线程、IO、网络请求等
- 该类的数据是全局的、共享的
- 该类的实例生命周期应该是全局的,在application整个生命周期中都会用到的
实现单例模式的几种方法
实现单例模式需要关注几个关键点
- 构造函数私有化,即权限设置为private
- 通过一个构造方法或者枚举返回单例类对象
- 确保单例类的对象只有一个,尤其是多线程的情况下
- 确保单例对象在反序列表不会重复创建对象
构造函数的私有化,确保了使用者不能够通过new来创建单例类的实例对象,该类暴露给外界一个获取唯一实例的方法,同样还需要保证线程安全,不能够在多线程的时候出现单例类存在多个对象的情况,即单例类在生命周期中只能存在一个实例供外界使用。
实现单例的方式
饿汉式
private static Singleton singleton= new Singleton(); private Singleton(){ } private static Singleton getInstance(){ return singleton }
饿汉式由于类加载时就创建好了对象,不存在线程安全和效率的问题,缺点是过早的创建了对象,而且不能够传递参数。
肯定也没人这么写,假如有推出去斩了
懒汉式
//定义一个实例 private static Singleton singleton = null; /** * 构造函数私有化 */ private Singleton() { } /** * 提供一个静态函数,获取实例,synchronized进行同步 * @return */ public static synchronized Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; }
这种方式简单,但是每次创建实例对象的时候都需要同步,同步是需要消耗资源的,效率低,不建议使用
Double Check Lock实现单例——改进的懒汉式
目前使用最广泛的单例,线程安全并且效率不低,可以考虑使用
//定义一个实例 private volatile static Singleton singleton = null; /** * 构造函数私有化 */ private Singleton() { } /** * 提供一个静态函数,获取实例,synchronized进行同步 * * @return */ public static Singleton getInstance() { if (singleton == null) {//第一次检查 synchronized (Singleton.class) {//lock if (singleton == null) {//第二次检查 singleton = new Singleton(); } } } return singleton; }
注意到使用了volatile关键字修饰单例对象,这样可以保证singleton对象每次都从主内存中读取,从而避免了由与java内存模型带来不必要的麻烦。
synchronize没有加在方法上,而是加在了方法体上,调用该方法的时候先检查实例对象为空,为空的时候加同步(防止多线程出现多个实例的情况),并且再次判断实例是否为空,为空就创建。这种方式只会在第一次实例为空的情况下同步,克服了懒汉式模式下每次都需要同步的情况,避免了不必要的开支
静态内部类实现单例
比较好的单例,线程安全,保证唯一,延迟实例化。建议选用
/** * 构造函数私有化 */ private Singleton() { } /** * 私有内部静态类,利用了加载外部类的时候内部类不会立即被加载的特性 */ private static class SingletonHolder{ private static Singleton singleton = new Singleton(); } /** * 提供一个静态函数,获取实例 * * @return */ public static Singleton getInstance() { return SingletonHolder.singleton; }
使用了java内部类的加载机制,只有内部类的静态成员被调用的时候才会加载静态内部类,所以会延迟加载
枚举单例
public enum Singleton { SINGLETON; private Singleton(){ }}
枚举和java中其他类一样,不仅可以有字段,也可以有自己的方法,如果我们需要一个对象来实现一个简单的事件(显示Toast),就可以使用枚举,枚举默认就是单一实例的并且创建默认是线程安全的
使用容器使用单例
private static Map<String, Object> instanceMap = new HashMap<String, Object>(); private Singleton() { } public static void putInstance(String key, Object instance) { if (!instanceMap.containsKey(key)) { instanceMap.put(key, instance); } } public static Object getInstance(String key){ return instanceMap.get(key); }
这种单例模式在Android源码中有用到,在单例比较多的时候,通过容器来管理和获取单例实例是一个不错的办法,通常在程序初始化的时候会将多个单例实例存到容器中,这样可以管理这些实例,下次使用直接取。
总结
单例模式是面向对象设计模式中应用最简单、最广泛的一种设计模式
- 单例模式的优点
- 提高了系统的性能
- 减少了系统内存的开销
- 单例模式避免对资源的多重占用保证系统整体的协调
- 单例对象可以设置全局的通讯站点, 优化和共享资源访问
- 单例迷失的缺点
- 单例模式一般不存在接口,也不是抽象的,不易拓展,如要拓展需要改变类的源代码,这和开闭原则相违背
- 单例模式的对象很容易产生一些问题,如:如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
- 单例类的职责过重,某种程度违背了单一职责原则
- Android设计模式解析(二)单例模式(Singleton Pattern)
- Android设计模式-单例模式(Singleton Pattern)
- Android设计模式之单例模式(Singleton Pattern)
- 二、单例模式(Singleton Pattern)
- java设计模式—单例设计模式(Singleton Pattern)完全解析
- 设计模式(一):单例模式(Singleton Pattern)
- AS3设计模式之一:单例模式(Singleton Pattern)
- 设计模式4:Singleton Pattern (单例模式)
- 深入浅出设计模式-005:单例模式(Singleton Pattern)
- 设计模式-单例模式(Singleton Pattern)
- 设计模式笔记7:单例模式(Singleton Pattern)
- 浅谈 java 设计模式--单例模式(Singleton pattern)
- Java设计模式 - 单例模式(Singleton Pattern)
- C++设计模式之Singleton pattern(单例模式)
- 设计模式原来如此-单例模式(Singleton Pattern)
- AS3设计模式之一:单例模式(Singleton Pattern)
- 设计模式之单例模式(Singleton Pattern)
- 设计模式(一)单例模式 Singleton pattern
- Git操作-撤销修改
- 克隆二叉树
- ExtJS onready,define,create
- javascript中判断对象是否为空几种场景
- 127.0.0.1 & localhost
- Android设计模式解析(二)单例模式(Singleton Pattern)
- 使用webpack快速搭建最简单ES6环境
- 超文本传输协议Http
- Java关键字final、static使用总结
- basePath
- NLP入门实例推荐(Tensorflow实现)
- interceptor
- Spring4.3.3、SpringMVC和Hibernate4.3.11集成问题之数据库插入操作无效
- okhttp上传多张图片核心代码