作用:
保证在Java应用程序中,一个类Class只有一个实例存在。
好处:
由于单例模式在内存中只有一个实例,减少了内存开销。
单例模式可以避免对资源的多重占用,例如一个写文件时,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作。
单例模式可以再系统设置全局的访问点,优化和共享资源访问。
使用情况:
建立目录 数据库连接的单线程操作
某个需要被频繁访问的实例对象
使用方法
第一种形式:
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
1.2android中的Singleton
软键盘管理的 InputMethodManager
源码(以下的源码都是5.1的):
public final class InputMethodManager {
//.........
static InputMethodManager sInstance;
//.........
public static InputMethodManager getInstance() {
synchronized (InputMethodManager.class) {
if (sInstance == null) {
IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
sInstance = new InputMethodManager(service, Looper.getMainLooper());
}
return sInstance;
}
}
使用的是第二种同步代码块的单例模式(可能涉及到多线程),类似的还有
AccessibilityManager(View获得点击、焦点、文字改变等事件的分发管理,对整个系统的调试、问题定位等)
BluetoothOppManager等。
当然也有同步方法的单例实现,比如:CalendarDatabaseHelper
public static synchronized CalendarDatabaseHelper getInstance(Context context) {
if (sSingleton == null) {
sSingleton = new CalendarDatabaseHelper(context);
}
return sSingleton;
}
注意Application并不算是单例模式
public class Application extends ContextWrapper implements ComponentCallbacks2 {
public Application() {
super(null);
}
在Application源码中,其构造方法是公有的,意味着可以生出多个Application实例,但为什么Application能实现一个app只存在一个实例呢?请看下面:
在ContextWrapper源码中:
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
ContextWrapper构造函数传入的base为null, 就算有多个Application实例,但是没有通过attach()绑定相关信息,没有上下文环境,三个字。
然并卵