《Android源码设计模式》--单例模式
No1:
懒汉单例模式优缺点分析
- public class Singleton{
- private static Singleton instance;
- private Singleton(){}
- public static synchronized Singleton getInstance(){
- if(instance == null){
- instance = new Singleton();
- }
- return instance;
- }
- }
优点:单例只有在使用时才会被实例化,在一定程度上节约了资源
缺点:第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都进行同步,造成不必要的同步开销。
所以这种模式一般不建议使用
No2:
Double Check Lock(DCL)双重检查锁定方式
- public class Singleton{
- private static Singleton sInstance = null;
- private Singleton(){}
- public void doSomething(){
- System.out.println("do sth.");
- }
- public static Singleton getInstance(){
- if(mInstance == null){
- synchronized(Singleton.class){
- if(mInstance == null){
- sInstance = new Singleton();
- }
- }
- }
- return sInstance;
- }
- }
优点:,第一次执行getInstance时单例对象才会被实例化,资源利用率高。第一层对instance判空主要是为了避免不必要的同步,第二层判断则是为了在null的情况下创建实例
缺点:第一次加载时反应稍慢,也由于java内存模型的原因偶尔会失败。再高并发环境下也有一定缺陷,虽然发生概率很小
No3:
静态内部类单例模式
- public class Singleton{
- private Singleton(){}
- public static Singleton getInstance(){
- return SingletonHolder.sInstance;
- }
- /**
- *静态内部类
- */
- private static class SingletonHolder{
- private static final Singleton sInstance = new Singleton();
- }
- }
第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,这种方式不仅能够确保线程安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化,所以推荐使用
No4:
枚举单例
- public enum SingletonEnum{
- INSTANCE;
- public void doSomething(){
- System.out.println("do sth.");
- }
- }
优点:线程安全,即使反序列化也不会重新生成新的实例
No5:
如果想杜绝单例模式对象在被反序列化时重新生成对象,那么必须加入readResolve函数
- public final class Singleton implements Serializable{
- private static final long serialVersionUID = 0L;
- private static final Singleton INSTANCE = new Singleton();
- private Singleton(){}
- public static Singleton getInstance(){
- return INSTANCE;
- }
- private Object readResolve() throws ObjectStreamException{
- return INSTANCE;
- }
- }
也就是在readResolve方法中将单例对象返回,而不是重新生成一个新的对象。而对于枚举,并不存在这个问题
No6:
1)可序列化类中的字段类型不是Java的内置类型,那么该字段类型也需要实现Serializable接口
2)如果调整了可序列化类的内部结构,例如新增、去除某个字段,但没有修改serialVersionUID,会引发异常。最好的方案是将值设置为0L,只是那些新修改的字段会为0或者null。
No7:
使用容器实现单例模式
- public class SingletonManager{
- private static Map<String,Object> objMap = new HashMap<String,Object>();
- private SingletonManager(){}
- 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);
- }
- }
优点:可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。
No8:
LayoutInflater.from(Context)来获取LayoutInflater服务
Context是抽象类,在Application、Activity、Service中都会存在一个Context对象,即Context的总个数为Activity个数+Service个数+1。
一个Activity的入口是ActivityThread的main函数。
创建Context对象的实现类是ContextImpl
No9:
从ContextImpl类的部分代码中可以看到,在虚拟机第一次加载该类时会注册各种ServiceFetcher,其中就包含了LayoutInflater Service。将这些服务以键值对的形式存储在一个HashMap中,用户使用时只需要根据key来获取到对应的ServiceFetcher,然后通过ServiceFetcher对象的getService函数来获取具体的服务对象。当第一次获取时,会调用ServiceFetcher的createService函数创建服务对象,然后将该对象缓存到一个列表中,下次再取值时直接从缓存中获取,避免重复创建对象,从而达到单例的效果。系统核心服务以单例形式存在,减少了资源消耗。
No10:
LayoutInflater是一个抽象类,PolicyManager实际上是一个代理类,实现了IPolicy接口
真正LayoutInflater的实现类是PhoneLayoutInflater
No11:
Activity的setContentView方法实际上调用的是Window的setContentView,Window是一个抽象类,具体实现类是PhoneWindow
No12:
createView相对比较简单,如果有前缀,那么构造View的完整路径,并且将该类加载到虚拟机中,然后获取该类的构造函数并且缓存起来,再通过构造函数来创建该View的对象,最后将View对象返回,这就是解析单个View的过程。通过rInflate的解析之后,整棵视图树就构建完毕。
No13:
单例模式的缺点:
1)单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现
2)单例对象如果持有Context,那么很容易引发内存泄露,此时需要注意传递给单例对象的Context最好是Application Context
No14:
Window的View层级图
《Android源码设计模式》--单例模式的更多相关文章
- <人人都懂设计模式>-单例模式
这个模式,我还是了解的. 书上用了三种不同的方法. class Singleton1: # 单例实现方式1 __instance = None __is_first_init = False def ...
- <人人都懂设计模式>-装饰模式
书上,真的用一个人穿衣打拌来讲解装饰模式的呢. from abc import ABCMeta, abstractmethod class Person(metaclass=ABCMeta): def ...
- <人人都懂设计模式>-中介模式
真正的用房屋中介来作例子, 好的书籍总是让人记忆深刻. class HouseInfo: def __init__(self, area, price, has_window, has_bathroo ...
- <人人都懂设计模式>-状态模式
同样是水,固态,气态,液态的变化,是由温度引起. 引此为思考状态模式. from abc import ABCMeta, abstractmethod # 引入ABCMeta和abstractmeth ...
- 人人都懂区块链--pdf电子版学习资料下载
人人都懂区块链 21天从区块链“小白”到资深玩家电子版pdf下载 链接:https://pan.baidu.com/s/1TWxYv4TLa2UtTgU-HqLECQ 提取码:6gy0 好的学习资料需 ...
- 【人人都懂密码学】一篇最易懂的Java密码学入门教程
密码与我们的生活息息相关,远到国家机密,近到个人账户,我们每天都在跟密码打交道: 那么,密码从何而来?生活中常见的加密是怎么实现的?怎么保证个人信息安全?本文将从这几方面进行浅谈,如有纰漏,敬请各位大 ...
- 人人都懂的HTML基础知识-HTML教程(1)
01.HTML基础简介 HTML (HyperText Markup Language,超文本标记语言) 不是一门编程语言,而是一种用于定义内容结构的标记语言,用来描述网页内容,文件格式为.html. ...
- JavaScript设计模式-单例模式、模块模式(转载 学习中。。。。)
(转载地址:http://technicolor.iteye.com/blog/1409656) 之前在<JavaScript小特性-面向对象>里面介绍过JavaScript面向对象的特性 ...
- 设计模式 单例模式(Singleton) [ 转载2 ]
设计模式 单例模式(Singleton) [ 转载2 ] @author java_my_life 单例模式的结构 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类 ...
- 设计模式 单例模式(Singleton) [ 转载 ]
设计模式 单例模式(Singleton) [ 转载 ] 转载请注明出处:http://cantellow.iteye.com/blog/838473 前言 懒汉:调用时才创建对象 饿汉:类初始化时就创 ...
随机推荐
- ElasticSearch关键概念
Elasticsearch 添加索引 一个存储关联数据的地方 用来指向一个或者多个分片(shards)的逻辑命名空间(logical namespcase) 应用程序直接与索引通信 一个分片(shar ...
- centos无法通过ssh连接的解决
系统环境是centos7,虚拟机环境下的.在使用ssh工具连接虚拟机的时候发现连接不上,用的是root 先检查openssh-server是否安装: yum list installed | grep ...
- 同一个IIS绑定多个Htts 站点问题
默认情况一个服务器的IIS只能绑定一个HTTPS也就是443端口 要实现多个站点对应HTTPS只能更改IIS配置 地址:C:Windowssystem32inetsrvconfigapplicatio ...
- Sparse AutoEncoder简介
1. AutoEncoder AutoEncoder是一种特殊的三层神经网络, 其输出等于输入:\(y^{(i)}=x^{(i)}\), 如下图所示: 亦即AutoEncoder想学到的函数为\(f_ ...
- 【转】WPF绑定模式
源地址:http://www.cnblogs.com/zjz008/archive/2010/05/26/1744802.html http://blog.csdn.net/haylhf/articl ...
- 【转】C#使用PrintDocument打印 多页 打印预览
PrintDocument实例所有的订阅事件如下: 创建一个PrintDocument的实例.如下: System.Drawing.Printing.PrintDocument docToPrint ...
- canvas画布,写字板
<!doctype html><html><head> <meta charset="utf-8"> <meta http-e ...
- Informatica学习:2、配置存储库服务和集成服务
继续上一篇的1.安装介质的获取与安装,本文介绍服务端的存储库服务和集成服务的配置. 安装好Informatica的客户端和服务端后,需要登陆Administration Console,配置存储库服务 ...
- beego项目运行过程
一:首先man.go,整个程序的入口 func main() { beego.Run() } 然后beego.run()代码 // Run beego application. // beego.Ru ...
- Django-ORM简介
ORM简介 MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库 ORM是“对象-关系-映射”的简称 ...