***************************************************************************************************************************
作者:EasyWave 时间:2013.02.16
类别:Android系统源码分析 声明:转载,请保留链接
注意:如有错误,欢迎指正。这些是我学习的日志文章......
***************************************************************************************************************************
一:什么是单例模式
单例模式也称为单件模式、单子模式,可能是使用最广泛的设计模式。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。单例模式有许多种实现方法,在C++中,甚至可以直接用一个全局变量做到这一点。使用全局对象能够保证方便地访问实例,但是不能保证只声明一个对象——也就是说除了一个全局实例外,仍然能创建相同类的本地实例。《设计模式》中文版一书中给出了一种很不错的实现,在84页开始讲这个单例模式。具体的可以参考书中所说。
二:单例模式的优点
1) 对唯一实例的受控访问
因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它。
2) 缩小名空间
Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间。
3) 允许对操作和表示的精化
Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用你所需要的类的实例在运行时刻配置应用。
4) 允许可变数目的实例
这个模式使得你易于改变你的想法,并允许Singleton类的多个实例。此外,你可以用相同的方法来控制应用所使用的实例的数目。只有允许访问Singleton实例的操作需要改变。
5) 比类操作更灵活
另一种封装单件功能的方式是使用类操作(即C + +中的静态成员函数或者是Smalltalk中的类方法)。但这两种语言技术都难以改变设计以允许一个类有多个实例。此外,C++中的静态成员函数不是虚函数,因此子类不能多态的重定义它们。
三:Android系统中实现的单例模式
在Android系统中,我们可以在很多地方看到这种设计模式,比如ProcessState类、IPCThreadState类等。我们还是来看看他们的实现代码吧。在frameworks\base\libs\binder\ProcessState.cpp文件中我们可以看到如下的定义:
而sp<ProcessState> self()定义是在frameworks\base\include\binde\ProcessState.h文件中,如下:
仔细看红色圈中的部分,从上面的代码中,我们看出这是一个典型的C++的单例模式,gProcess是在Static.cpp中定义的,用户访问唯一实例的方法只有self()成员函数。如果不通过这个函数,任何创建实例的尝试都将失败,因为类的构造函数是私有的。self()使用懒惰初始化,也就是说它的返回值是当这个函数首次被访问时被创建的。这是一种防弹设计——所有self()之后的调用都返回相同实例的指针,那么它是如何调用的呢?如下:[在frameworks\base\cmds\app_process\App_main.cpp]
在Andriod中,还有一个地方,这里需要特别的说说,就是在frameworks\base\libs\binder\IPCThreadState.cpp文件中,这个关于binder的进程间通信的类函数集合。它的调用方式采用了TLS,也就是线程局部存储(Thread Local Storage,TLS)。Andriod是一个多线程的系统,每个线程除了共享进程的资源外还拥有各自的私有资源:
一个寄存器组(或者说是线程上下文);
一个专属的堆栈;
一个专属的消息队列;
一个专属的Thread Local Storage(TLS);
一个专属的结构化异常处理串链。
这里重点关注Thread Local Storage,我们还是来看看具体的代码实现吧,如下:
不错,pthread_getspecific()和pthread_key_create()函数就是一个关于TLS相关的函数。详细的关于线程的概念,请参考:《POSIX多线程程序设计》这本书。这本书详细的解释了Linux下的线程的概念。这里采用了TLS来作为用户访问唯一实例。这个地方用的非常巧妙...... 深入的知识点就不说了......
如何调用呢?请看frameworks\base\core\jni\android_util_Binder.cpp中的static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name)函数,如下:
在Andriod的源码中,很多地方采用可复用面向对象软件的设计模式,所以,建议还是先看看《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》,可以在下面的地址下载,分C++版和Java版:
C++版:http://wenku.baidu.com/view/69b6c04b2b160b4e767fcff5.html
Java版:http://wenku.baidu.com/view/bbf5e9d633d4b14e85246884.html