广告
返回顶部
首页 > 资讯 > 移动开发 >Android设计模式之单例模式
  • 400
分享到

Android设计模式之单例模式

单例模式Android 2022-06-06 12:06:39 400人浏览 薄情痞子
摘要

  1、单例模式常见情景   设计模式中,简单不过的是单例模式。先看看单例模式   Singleton模式可以是很简单的,它的全部只需要一个类可以完成(看看这章可怜的U

  1、单例模式常见情景   设计模式中,简单不过的是单例模式。先看看单例模式   Singleton模式可以是很简单的,它的全部只需要一个类可以完成(看看这章可怜的UML图)。但是如果在“对象创建的次数以及何时被创建”这两点上较真起来,Singleton模式可以相当的复杂,比头五种模式加起来还复杂,譬如涉及到DCL双检测(double checked locking)的讨论、涉及到多个类加载器(ClassLoader)协同时、涉及到跨JVM集群、远程EJB等)时、涉及到单例对象被销毁后重建等。   目的:   希望对象只创建一个实例,并且提供一个全局的访问点。

图6.1 单例模式的UML图

  结构是简单的,但是却存在一下情况;   1.每次从getInstance()都能返回一个且的一个对象。   2.资源共享情况下,getInstance()必须适应多线程并发访问。   3.提高访问性能。   4.懒加载(Lazy Load),在需要的时候才被构造。   首先实现1中的单例模式A:   4.public class SingletonA {      5.       6.          9.    private static SingletonA instance = null;      10.       11.    public static SingletonA getInstance() {      12.        if (instance == null) {                              //line 12      13.            instance = new SingletonA();          //line 13      14.        }      15.        return instance;      16.    }      17.}      这个写法我们把四点需求从上往下检测,发现第2点的时候出了问题,假设这样的场景:两个线程并发调用Singleton.getInstance(),假设线程一先判断完instance是否为null,既代码中的line 12进入到line 13的位置。刚刚判断完毕后,JVM将CPU资源切换给线程二,由于线程一还没执行line 13,所以instance仍然是空的,因此线程二执行了new Signleton()操作。片刻之后,线程一被重新唤醒,它执行的仍然是new Signleton()操作。所以这种设计的单例模式不能满足第2点需求。   下面我们继续   实现2中单例模式B:   4.public class SingletonB {      5.       6.          9.    private static SingletonB instance = null;      10.       11.    public synchronized static SingletonB getInstance() {      12.        if (instance == null) {      13.            instance = new SingletonB();      14.        }      15.        return instance;      16.    }      17.}      比起单例A仅仅在方法中多了一个synchronized修饰符,现在可以保证不会出线程问题了。但是这里有个很大(至少耗时比例上很大)的性能问题。除了第一次调用时是执行了SingletonKerriganB的构造函数之外,以后的每一次调用都是直接返回instance对象。返回对象这个操作耗时是很小的,绝大部分的耗时都用在synchronized修饰符的同步准备上,因此从性能上说很不划算。   实现3单例模式C:   4.public class SingletonC {      5.       6.          9.    private static SingletonKerriganD instance = null;      10.       11.    public static SingletonC getInstance() {      12.        if (instance == null) {      13.            synchronized (SingletonC.class) {      14.                if (instance == null) {      15.                    instance = new SingletonC();      16.                }      17.            }      18.        }      19.        return instance;      20.    }      21.}      看起来这样已经达到了我们的要求,除了第一次创建对象之外,其他的访问在第一个if中返回了,因此不会走到同步块中。已经完美了吗?   我们来看看这个场景:假设线程一执行到instance = new SingletonKerriganD()这句,这里看起来是一句话,但实际上它并不是一个原子操作(原子操作的意思是这条语句要么被执行完,要么没有被执行过,不能出现执行了一半这种情形)。事实上高级语言里面非原子操作有很多,我们只要看看这句话被编译后在JVM执行的对应汇编代码发现,这句话被编译成8条汇编指令,大致做了3件事情:   1.给Kerrigan的实例分配内存。   2.初始化Kerrigan的构造器   3.将instance对象指向分配的内存空间(注意到这步instance非null了)。   但是,由于Java编译器允许处理器乱序执行(out-of-order),以及jdk1.5之前JMM(Java Memory Medel)中Cache、寄存器到主内存回写顺序的规定,上面的第二点和第三点的顺序是无法保证的,也是说,执行顺序可能是1-2-3也可能是1-3-2,如果是后者,并且在3执行完毕、2未执行之前,被切换到线程二上,这时候instance因为已经在线程一内执行过了第三点,instance已经是非空了,所以线程二直接拿走instance,然后使用,然后顺理成章地报错,而且这种难以跟踪难以重现的错误估计调试上一星期都未必能找得出来,真是一茶几的杯具啊。   DCL的写法来实现单例是很多技术书、教科书(包括基于JDK1.4以前版本的书籍)上推荐的写法,实际上是不完全正确的。的确在一些语言(譬如C语言)上DCL是可行的,取决于是否能保证2、3步的顺序。在JDK1.5之后,官方已经注意到这种问题,因此调整了JMM、具体化了volatile关键字,因此如果JDK是1.5或之后的版本,只需要将instance的定义改成“private volatile static SingletonKerriganD instance = null;”可以保证每次都去instance都从主内存读取,可以使用DCL的写法来完成单例模式。当然volatile或多或少也会影响到性能,重要的是我们还要考虑JDK1.42以及之前的版本,所以本文中单例模式写法的改进还在继续。   代码倒越来越复杂了,现在先来个返璞归真,根据JLS(Java Language Specification)中的规定,一个类在一个ClassLoader中只会被初始化一次,这点是JVM本身保证的,那把初始化实例的事情扔给JVM好了.   实现4单例模式D:   4.public class SingletonD {      5.       6.          9.    private static SingletonD instance = new SingletonD();      10.       11.    public static SingletonD getInstance() {      12.        return instance;      13.    }      14.}      这种写法不会出现并发问题,但是它是饿汉式的,在ClassLoader加载类后Kerrigan的实例会第一时间被创建,饿汉式的创建方式在一些场景中将无法使用:譬如实例的创建是依赖参数或者配置文件的,在getInstance()之前必须调用某个方法设置参数给它,那样这种单例写法无法使用了。   可带参数单例模式E:   4.public class SingletonE {      5.       6.    private static class SingletonHolder {      7.              10.        static final SingletonE INSTANCE = new SingletonE();      11.    }      12.       13.    public static SingletonE getInstance() {      14.        return SingletonHolder.INSTANCE;      15.    }      16.}      这种写法仍然使用JVM本身机制保证了线程安全问题;由于SingletonHolder是私有的,除了getInstance()之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖JDK版本。   当然,用户以其它方式构造单例的对象,如果设计者不希望这样的情况发生,则需要做规避措施。其它途径创建单例实例的方式有:   1.直接new单例对象   2.通过反射构造单例对象   3.通过序列化构造单例对象。   对于第一种情况,一般我们会加入一个private或者protected的构造函数,这样系统不会自动添加那个public的构造函数了,因此只能调用里面的static方法,无法通过new创建对象。   对于第二种情况,反射时可以使用setAccessible方法来突破private的限制,我们需要做到第一点工作的同时,还需要在在 ReflectPermission("suppressAccessChecks") 权限下使用安全管理器(SecurityManager)的checkPermission方法来限制这种突破。一般来说,不会真的去做这些事情,都是通过应用服务器进行后台配置实现。   对于第三种情况,如果单例对象有必要实现Serializable接口(很少出现),则应当同时实现readResolve()方法来保证反序列化的时候得到原来的对象。   版单例模式F:   4.public class SingletonF implements Serializable {      5.       6.    private static class SingletonHolder {      7.              10.        static final SingletonF INSTANCE = new SingletonF();      11.    }      12.       13.    public static SingletonF getInstance() {      14.        return SingletonHolder.INSTANCE;      15.    }      16.       17.          20.    private SingletonF() {      21.    }      22.       23.          26.    private Object readResolve() {      27.        return getInstance();      28.    }      29.}      2、Android源码单例模式举例   1、日历模块   App路径:packages/providers/CalendarProvider   文件:packages/providers/CalendarProvider/src/com/android/provider/calendar/CalendarDatabaseHelper.java   单例代码:   private static CalendarDatabaseHelper sSingleton = null;        public static synchronized CalendarDatabaseHelper getInstance(Context context) {    if (sSingleton == null) {    sSingleton = new CalendarDatabaseHelper(context);    }    return sSingleton;    }    可以看出,这是用到了2中的单例模式B.   2.Collator类   文件:libcore/luni/src/main/java/com/ibm/icu4jni/text/Callator.java   libcore/luni/src/main/java/com/ibm/icu4jni/text/RuleBasedCallator.java   单例代码:   public static Collator getInstance(Locale locale) {    return new RuleBasedCollator(locale);    }    p;       RuleBasedCollator(Locale locale) {    m_collator_ = NativeCollation.openCollator(locale.toString());    }    static native int openCollator(String locale);    这是上面给出的单例模式E,可带参数的单例模式   3.Editable类   文件:frameworks/base/core/java/android/text/Editable.java   private static Editable.Factory sInstance = new Editable.Factory();        public static Editable.Factory getInstance() {    return sInstance;    }    可见这是单例模式D是实例应用   4.AccessibilityManager类   文件:frameworks/base/core/java/android/view/accessibility/AccessibilityManager.java   public static AccessibilityManager getInstance(Context context) {    synchronized (sInstanceSync) {    if (sInstance == null) {    sInstance = new AccessibilityManager(context);    }    }    return sInstance;    }    这是单例模式C的应用。   android使用单例模式的地方很多,特别是数据库创建时,会使用到单例模式。因每种单例模式试用场景不一样,所以android在不同地方使用了不同的单例模式实现方式。


--结束END--

本文标题: Android设计模式之单例模式

本文链接: https://www.lsjlt.com/news/28715.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android设计模式之单例模式
      1、单例模式常见情景   设计模式中,简单不过的是单例模式。先看看单例模式   Singleton模式可以是很简单的,它的全部只需要一个类可以完成(看看这章可怜的U...
    99+
    2022-06-06
    单例模式 Android
  • Android设计模式之单例模式实例
    目录一、概念1.1 单例类1.2 优缺点1.2.1 优点1.2.2 缺点二、创建单例模式的方法2.1 饿汉式2.2 懒汉式2.2.1 懒汉式(非线程安全)2.2.2 懒汉式(线程安全...
    99+
    2023-05-16
    Android单例模式 Android设计模式单例模式
  • Android设计模式系列之单例模式
     单例模式,可以说是GOF的23种设计模式中最简单的一个。 这个模式相对于其他几个模式比较独立,它只负责控制自己的实例化数量单一(而不是考虑为用户产生什么样的实例),...
    99+
    2022-06-06
    单例模式 Android
  • Android设计模式之单例模式详解
    单例模式一个类只有一个实例,并且可以全局访问使用应用场景如账户管理类,数据库操作类等(某个对象频繁被访问使用)常用方式饿汉式懒汉式同步加锁DCL双重加锁验证静态内部类枚举单例饿汉式加载类的同时立即进行初始化操作,对资源消耗很大public ...
    99+
    2023-05-30
    android 设计模式 单例模式
  • Android设计模式之单例模式解析
    在日常开发过程中时常需要用到设计模式,但是设计模式有23种,如何将这些设计模式了然于胸并且能在实际开发过程中应用得得心应手呢?和我一起跟着《Android源码设计模式解析与实战》一书边学边应用吧!今天我们要讲的是单例模式定义确保某一个类只有...
    99+
    2023-05-30
    android 单例模式 之单
  • Java设计模式之单例模式
    目录什么是设计模式?单例模式是什么?单例模式设计的原则是什么?Java实现单例模式的5种方式?懒汉饿汉静态内部类双重校验锁DCL(Double Check Lock)枚举(num)总...
    99+
    2022-11-12
  • C#设计模式之单例模式
    单例模式也是创建型模式的一种,也是23种设计模式中比较简单的一种。见名思意,在整个软件系统中,只有某个类型的一个对象,并且访问他的地方也只有一个,也就是只有一个全局对象访问点,这个实...
    99+
    2022-11-13
  • python设计模式之单例模式
    单例模式是一种创建型设计模式,它确保一个类有且只有一个特定类型的对象,并提供全局访问点。其意图为: 确保类有且只有一个对象被创建 为对象提供一个访问点,使程序可以全局访问该对象 控制共享资源的并行访问 简单理解:单例...
    99+
    2023-01-30
    模式 python
  • JavaScript设计模式之单例模式
    目录单例模式实现单例模式透明的单例模式用代理实现单例模式惰性单例通用的惰性单例小结单例模式 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的 ...
    99+
    2022-11-13
    JavaScript设计模式 JavaScript单例模式
  • android开发设计模式之——单例模式详解
    单例模式是设计模式中最常见也最简单的一种设计模式,保证了在程序中只有一个实例存在并且能全局的访问到。比如在Android实际APP 开发中用到的 账号信息对象管理, 数据库对象...
    99+
    2022-06-06
    设计模式 android开发 单例模式 Android
  • Android设计模式之单例模式怎么创建
    本篇内容介绍了“Android设计模式之单例模式怎么创建”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、概念单例模式是运用最广泛的设计模式...
    99+
    2023-07-06
  • .Net设计模式之单例模式(Singleton)
    一、动机(Motivation) 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。 如何绕过常规的构造器,提供一种...
    99+
    2022-11-13
  • java设计模式之单例模式解析
    单例模式是最简单但同时也是很重要的一种设计模式,优点有以下几个方面:当内存占用特别大的类需要频繁地创建销毁时,单例模式可以节省内存和提高性能,例如myBatis里面的sessionFactory当需要对文件做单一读写时,例如同一时间只能同时...
    99+
    2023-05-31
    java 设计模式 单例模式
  • Java设计模式之单例模式简介
    目录一、饿汉式(静态常量)二、饿汉式(静态代码块)三、懒汉式(线程不安全)四、懒汉式(线程安全,同步方法)五、懒汉式(线程不安全,同步代码块)六、双重检查( DCL )七、静态内部类...
    99+
    2022-11-12
  • C++设计模式之单例模式详解
    目录单例模式:就是只有一个实例。单例模式又分为两种基本的情形:饿汉式和懒汉式如下是懒汉式单例类小结:继续看单例模式总结单例模式:就是只有一个实例。 singleton pattern...
    99+
    2022-11-12
  • JAVA设计模式之单例模式详解
    目录前言一、单例模式是什么?二、懒汉式单例三、饿汉式单例四、双重校验锁总结前言 在之前的文章里已经介绍了设计模式以及设计原则的概念,接下来我们从单例模式入手深入学习几种常用的JAVA...
    99+
    2022-11-13
  • 【Java】设计模式之单例模式与工厂模式
    ✅作者简介:热爱后端语言的大学生,CSDN内容合伙人 ✨精品专栏:C++面向对象 🔥系列专栏:JavaSE精品总结 文章目录   前言1、设计模式概念及分类2、单例模式2...
    99+
    2023-10-04
    java 单例模式 设计模式
  • Java设计模式之单例模式示例详解
    目录0.概述1.饿汉式1.1 饿汉式单例实现1.2 破坏单例的几种情况1.3 预防单例的破坏2.枚举饿汉式2.1 枚举单例实现2.2 破坏单例3.懒汉式4.双检锁懒汉式5.内部类懒汉...
    99+
    2022-11-12
  • 每天一个设计模式之单例模式
    博主按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript(_靠这吃饭_)和python(_纯粹喜欢_)两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) 网速过慢的朋友...
    99+
    2023-01-31
    模式
  • Java创建型设计模式之单例模式
    目录介绍优点实现饿汉式懒汉式静态内部类枚举介绍 单例模式是一种创建型设计模式,其主要特点包括: 只有一个实例:单例模式确保系统中只有一个实例对象存在,所有对该对象的访问都是对同一个对...
    99+
    2023-05-18
    Java单例模式 Java创建型设计模式
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作