Android 设计模式--单例模式

一,定义 

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

二,使用场景

确保某个类只有一个对象的使用场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。例如,创建一个对象需要消耗过多的资源,如要访问IO和数据库等资源,就应该考虑单例模式了。

三,饿汉式单例

/*** 饿汉式单例模式* */
public class YuanZhen {private static final YuanZhen yuanzhen =new YuanZhen();private YuanZhen(){}public static YuanZhen getInstance(){return yuanzhen;}}

饿汉式优点: 不需要加锁,性能优越

饿汉式缺点:一开始就加载好了对象,占用内存

四,懒汉式单例

/*** 懒汉式单例* */
public class YuanZhen1 {private  static YuanZhen1 yuanZhen1;private YuanZhen1(){}public static synchronized YuanZhen1 getInstance(){if(yuanZhen1 ==null){yuanZhen1 =new YuanZhen1();}return yuanZhen1;}
}

懒汉式单例就是在需要的时候去创建对象。

懒汉式单例的优点:单例只有在使用的时候才去加载,一定程度上节约了资源

懒汉式单例的缺点:

1.第一次加载时需要实例化,运行稍慢

2.每次调用synchronized同步锁,消耗资源

3,虽然加了同步锁,但是仍然可能会出现同步问题

五,DCL 双重锁检查机制实现单例模式

/*** DCL单例* */
public class YuanZhen2 {private static YuanZhen2 yuanZhen2;private YuanZhen2(){}public static  YuanZhen2 getInstance(){if(yuanZhen2 == null){synchronized (YuanZhen2.class){if(yuanZhen2 ==null){yuanZhen2 =new YuanZhen2();}}}return yuanZhen2;}
}

在getInstance方法中,对yuanzhen2进行了2次判空,第一次判空是为了避免不必要的同步

第二次判空是为了在null的情况下创建实例

当线程A执行到new Yuanzhen2() 这句代码时,它最终会被编译成多条汇编指令:

1,给YuanZhen2的实例分配内存

2,调用YuanZhen2的构造函数,初始化成员变量

3,将yuanzhen2对象指向分配的内存空间

JDK1.5之前,它们在内存中的执行顺序可能1-2-3 也可能是1-3-2.

如果是1-3-2,那么如果执行完3之后,切换到了B线程,那这时yuanzhen2表面上看是非空,实际上是空的。那么后面再使用的时候就会报错,这就是DCL失效。

但是JDK1.5之后,调整了JVM.只需要将YuanZhen2的定义改成如下volatile方式,就能保证YuanZhen2对象每次都是从主内存中读取。

/*** DCL单例* */
public class YuanZhen2 {private static volatile YuanZhen2 yuanZhen2;private YuanZhen2(){}public static  YuanZhen2 getInstance(){if(yuanZhen2 == null){synchronized (YuanZhen2.class){if(yuanZhen2 ==null){yuanZhen2 =new YuanZhen2();}}}return yuanZhen2;}
}

volatile会影响性能,但是如果可以避免DCL的失效问题,这点性能几乎可以忽略不计了

DCL的优点:

1,资源利用率高,第一次执行getInstance时单例对象才被初始化

2,避免了多余的同步问题

3,避免了线程的并发问题

DCL的缺点:

1,第一次加载时反省稍慢

2,使用synchronized 和 volaile 关键字,性能有一定消耗

六,静态内部类实现单例

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

当第一次加载YuanZhen3类时,并不会初始化yuanzhen3,只有在第一次调用Yuanzhen3的getInstance方法时才会导致yuanzhen3被初始化,因此,第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,这种方式不仅能确保线程安全,也能够保证单例对象的唯一性,同时也延迟了单列的实例化,所以这是最推荐使用的方式。

七,枚举实现单例

/*** 枚举方式* */
public enum YuanZhen4 {INSTACE;
}

枚举方式是最简单的单例实现方式。而且它也是线程安全的,并且在任何情况下它都是一个单例。

在上述几种方式中,我们可以通过hook反序列化的函数readResolve来重新生成对象,除非我们重写readResolve函数将对象返回。但是枚举并不存在这个问题

八,使用容器实现单例

/*** 使用容器* */
public class YuanZhen5 {private static Map<String,Object> map =new HashMap<>();private YuanZhen5(){}public static void registerInstance(String key,Object instance){if(!map.containsKey(key)){map.put(key, instance);}}public static Object getInstance(String key){return map.get(key);}
}

使用:

YuanZhen5.registerInstance("1", YuanZhen1.getInstance());
YuanZhen5.registerInstance("2", YuanZhen2.getInstance());
YuanZhen2 yuanzhen2 = (YuanZhen2) YuanZhen5.getInstance("2");

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

优点:

1,方便管理多种类型的单例

2,使用时可以通过统一的接口进行获取操作,降低了用户的使用成本

3,对用户隐藏了具体实现

4,降低了耦合度

九,总结

单例模式优点:

1,单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁的创建,销毁时,单例模式的优势就非常明显了

2,由于单例模式只生成一个实例,所以,减少了系统的性能开销,当一个对象的创建需要比较多的资源时,则可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决。

缺点:

1,单例模式一般没有接口,扩展很难

2,单例对象如果持有context,很容易发生内存泄漏,此时需要注意,传递给单例对象的Context最好是Application Context。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/138892.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

node插件MongoDB(五)—— 库mongoose 的模块化(五)

文章目录 一、使用mongoose 模块化的原因二、准备工作2. 启动mongo.exe 和mongod.exe 两个程序连接数据库 三、基本模块的拆分1、基本逻辑2、代码3、代码图示说明 四、在index.js 中进一步的拆分1.拆分原因2.新建model文件夹存储文档的结构对象3.代码4.代码实际演示和注意点 一…

mysql从A库复制表到B库的时候报:MySQL ERROR:1153

今天操作数据表从A库迁移到B库的时候报了这个问题: MySQL ERROR&#xff1a;1153&#xff1b;因为表比较大&#xff0c;我导出SQL文件查看大概有1.8G&#xff0c;里面存放的都是图片信息。我其中尝试了多种方法&#xff0c;使用navicat 工具中的数据 同步&#xff0c;还有表复制…

线性代数-Python-05:矩阵的逆+LU分解

文章目录 1 矩阵的逆1.1 求解矩阵的逆 2 初等矩阵2.1 初等矩阵和可逆性 3 矩阵的LU分解3.1 LU分解的实现 1 矩阵的逆 1.1 求解矩阵的逆 def inv(A):if A.row_num() ! A.col_num():return Nonen A.row_num()"""矩阵A单位矩阵"""ls LinearSyste…

SplayTree高分测试用例

测试用例结果展示 覆盖率 变异得分 测试注意点 从SplayTree测起&#xff0c;然后再测SubSplayTree&#xff0c;因为前者调用后者。SplaySubTree的remove方法大部分内容需要通过反射才能测到。value和index在SplayTree当中都不是唯一的。一个index可能对应多个value。 不足之…

Azure 机器学习 - 如何使用模板创建安全工作区

目录 先决条件了解模板配置模板连接到工作区疑难解答错误&#xff1a;Windows 计算机名的长度不能超过 15 个字符&#xff0c;并且不能全为数字或包含以下字符 本教程介绍如何使用 [Microsoft Bicep]和 [Hashicorp Terraform]模板创建以下 Azure 资源&#xff1a; Azure 虚拟网…

AndroidStudio gitee令牌过期 解决方式 remote:Oauth: Access token is expired

记一次&#xff0c;gitee令牌过期 解决方式 Oauth: Access token is expired fatal: unable to access ‘https://gitee.com/xxxx.git/’: The requested URL returned error: 403 remote: [session-e14669a3] Oauth: Access token is expired fatal: unable to access https…

网页分析和xml.etree库

源代码&#xff1a; Lib/xml/etree/ElementTree.py 该xml.etree.ElementTree模块实现了一个简单高效的 API&#xff0c;用于解析和创建 XML 数据。 一、说明 这是一个简短的使用教程xml.etree.ElementTree&#xff08;ET简而言之&#xff09;。目标是演示该模块的一些构建块和基…

Javaweb之javascript的DOM对象的详细解析

1.5.3 DOM对象 1.5.3.1 DOM介绍 DOM&#xff1a;Document Object Model 文档对象模型。也就是 JavaScript 将 HTML 文档的各个组成部分封装为对象。 DOM 其实我们并不陌生&#xff0c;之前在学习 XML 就接触过&#xff0c;只不过 XML 文档中的标签需要我们写代码解析&#x…

[PHP]Kodexplorer可道云 v4.47

KodExplorer可道云&#xff0c;原名芒果云&#xff0c;是基于Web技术的私有云和在线文件管理系统&#xff0c;由上海岱牧网络有限公司开发&#xff0c;发布于2012年6月。致力于为用户提供安全可控、可靠易用、高扩展性的私有云解决方案。 用户只需通过简单环境搭建&#xff0c;…

虚幻引擎:如何进行关卡切换?无缝切换?

一丶非无缝切换 在切换的时候会先断开连接,等创建好后才会链接,造成体验差 蓝图中用到的节点是 Execute Console Command 二丶无缝切换 链接的时候不会断开连接,中间不会出现卡顿,携带数据转换地图 1.需要在gamemode里面开启无缝漫游,开启之后使用上面的切换方式就可以做到无缝…

ESP32 C3 smartconfig一键配网报错

AP配网 在调试我的esp32c3的智能配网过程中&#xff0c;发现ap配网使用云智能App是可以正常配置的。 切记用户如果在menu菜单里使能AP配网&#xff0c;默认SSID名字为adh_PK值_MAC后6位。用户可以修改这个apssid的键值&#xff0c;但是要使用云智能app则这个名字的开头必须为ad…

什么是Amazon Simple Email Service(SES 群发邮件)

Amazon Simple Email Service&#xff08;Amazon SES&#xff09;让您可以使用 Amazon SES API 或 SMTP 接口放心地联络到客户&#xff0c;而无需使用本地简单邮件传输协议&#xff08;Simple Mail Transfer Protocol&#xff0c;SMTP&#xff09;电子邮件服务器。 目录 什么是…

win10网络和Internet设置

win10网络设置 win10进入网络设置的常用入口有两个 第一个入口 桌面右下角右键网络图标&#xff0c;然后打开“网络和Internt设置” 第二个入口 桌面的“我的网络”快捷方式&#xff0c;或者我的电脑进去后&#xff0c;左侧栏找到“网络” 右键“属性” 可以看到&#xff0c;…

魔搭社区LLM模型部署实践, 以ChatGLM3为例(一)

魔搭社区LLM模型部署实践&#xff0c; 以ChatGLM3为 例 本文以ChatGLM3-6B为例&#xff0c; 主要介绍在魔搭社区如何部署LLM&#xff0c; 主要包括如下内容&#xff1a; ● SwingDeploy - 云端部署&#xff0c; 实现零代码一键部署 ● 多端部署 - MAC个人笔记本&#xff0c;…

时序预测 | MATLAB实现WOA-CNN-GRU-Attention时间序列预测(SE注意力机制)

时序预测 | MATLAB实现WOA-CNN-GRU-Attention时间序列预测&#xff08;SE注意力机制&#xff09; 目录 时序预测 | MATLAB实现WOA-CNN-GRU-Attention时间序列预测&#xff08;SE注意力机制&#xff09;预测效果基本描述模型描述程序设计参考资料 预测效果 基本描述 1.MATLAB实现…

米软科技 | 推进医院智慧管理分级评估体系建立、提升评级

国家卫生健康委办公厅于2021年3月15日发布了“关于印发医院智慧管理分级评估标准体系&#xff08;试行&#xff09;的通知”&#xff08;国卫办医函〔2021〕86 号&#xff09;&#xff0c;该评估体系用于指导医疗机构科学、规范开展智慧医院建设&#xff0c;提升医院管理精细化…

Spring Cloud学习(六)【统一网关 Gateway】

文章目录 网关的功能搭建网关服务路由断言工厂Route Predicate Factory路由过滤器 GatewayFilter过滤器执行顺序跨域问题处理 网关的功能 网关功能&#xff1a; 身份认证和权限校验服务路由、负载均衡请求限流 在SpringCloud中网关的实现包括两种&#xff1a; gatewayzuul …

spring boot configuration annotation processor notconfigured解决方法

spring boot configuration annotation processor notconfigured解决方法 一、问题描述二、解决方法 一、问题描述 我在使用ConfigurationProperties注解的时候idea出现提示信息spring boot configuration annotation processor notconfigured&#xff0c;但是却不影响程序的运…

基于ubuntu22.04手动安装openstack——2023.2版本(最新版)的问题汇总

前言&#xff1a;基本上按照openstack官方网站动手可以搭建成功&#xff08;如有需要私信发部署文档&#xff09;。 但是任然有些小问题&#xff0c;所以汇总如下。 第一个问题 问题&#xff1a; ubuntu搭建2023.2版本neutorn报错&#xff0c;ERROR neutron.plugins.ml2.driv…

ArcGIS进阶:栅格计算器里的Con函数使用方法

本实验操作为水土保持功能重要性评价&#xff1a; 所用到的数据包括&#xff1a;土地利用类型数据&#xff08;矢量&#xff09;、植被覆盖度数据&#xff08;矢量&#xff09;和地形坡度数据&#xff08;栅格&#xff09;。 由于实验数据较少&#xff0c;其思路也较为简单&a…