#1. Singleton(单例模式)
作用:
保证在Java应用程序中,一个类Class只有一个实例存在。
好处:
由于单例模式在内存中只有一个实例,减少了内存开销。
单例模式可以避免对资源的多重占用,例如一个写文件时,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作。
单例模式可以再系统设置全局的访问点,优化和共享资源访问。
使用情况:
建立目录 数据库连接的单线程操作
某个需要被频繁访问的实例对象
##1.1 使用方法
第一种形式:
public class Singleton {
/* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */
private static Singleton instance = null;
/* 私有构造方法,防止被实例化 */
private Singleton() {
}
/* 懒汉式:第一次调用时初始Singleton,以后就不用再生成了
静态方法,创建实例 */
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
但是这有一个问题,不同步啊!在对据库对象进行的频繁读写操作时,不同步问题就大了。
第二种形式:
既然不同步那就给getInstance方法加个锁呗!我们知道使用synchronized关键字可以同步方法和同步代码块,所以:
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
或是
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
return instance;
}
获取Singleton实例:
Singleton.getInstance().方法()
##1.2android中的Singleton
软键盘管理的 InputMethodManager
源码(以下的源码都是5.1的):
205 public final class InputMethodManager {
//.........
211 static InputMethodManager sInstance;
//.........
619 public static InputMethodManager getInstance() {
620 synchronized (InputMethodManager.class) {
621 if (sInstance == null) {
622 IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
623 IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
624 sInstance = new InputMethodManager(service, Looper.getMainLooper());
625 }
626 return sInstance;
627 }
628 }
使用的是第二种同步代码块的单例模式(可能涉及到多线程),类似的还有 AccessibilityManager(View获得点击、焦点、文字改变等事件的分发管理,对整个系统的调试、问题定位等) BluetoothOppManager等。
当然也有同步方法的单例实现,比如:CalendarDatabaseHelper
307 public static synchronized CalendarDatabaseHelper getInstance(Context context) {
308 if (sSingleton == null) {
309 sSingleton = new CalendarDatabaseHelper(context);
310 }
311 return sSingleton;
312 }
注意Application并不算是单例模式
44 public class Application extends ContextWrapper implements ComponentCallbacks2 {
79 public Application() {
80 super(null);
81 }
在Application源码中,其构造方法是公有的,意味着可以生出多个Application实例,但为什么Application能实现一个app只存在一个实例呢?请看下面:
在ContextWrapper源码中:
50 public class ContextWrapper extends Context {
51 Context mBase;
52
53 public ContextWrapper(Context base) {
54 mBase = base;
55 }
64 protected void attachBaseContext(Context base) {
65 if (mBase != null) {
66 throw new IllegalStateException("Base context already set");
67 }
68 mBase = base;
69 }
ContextWrapper构造函数传入的base为null, 就算有多个Application实例,但是没有通过attach()绑定相关信息,没有上下文环境,三个字。
然并卵