文章出處
文章列表
簡介
單例模式使得一個類的實例是唯一的,外部對它的訪問都針對同一個對象。
單例模式的使用可以是業務上的原因,比如一個User對象需要全局唯一,或者是性能上的考慮,避免創建代價較高的對象反復實例化。
實現方式
- 餓漢式:性能不是問題時,且對象一定需要被實例化,線程安全
public class User {
private static final User ourInstance = new User();
public static User getInstance() {
return ourInstance;
}
private User() {
}
}
- 雙重鎖定
線程安全,較高的性能,無需每次都加鎖
public class User {
private static volatile User ourInstance;
public static User getInstance() {
if (ourInstance == null) {
synchronized (User.class) {
if (ourInstance == null) {
ourInstance = new User();
}
}
}
return ourInstance;
}
private User() {
}
}
- 靜態內部類
僅在第一次調用getInstance()時,發生實例化,而且字段初始化語句是線程安全的。
public class User {
public static User getInstance() {
return Holder.ourInstance;
}
private static class Holder {
private static User ourInstance = new User();
}
private User() {
}
}
單例集合
可以使用一個HashMap等集合來維護需要的單例對象,初始化放在程序啟動時或其它合適的時機。此時可以根據對象的不同方面對它進行分類,而且最終得到同一個實例。
此時使用到的類型本身無需是單例的,這種形式處理app中會用到的若干個全局對象時蠻合適。單例數據結構
像android中就有一個下面的幫助類,它為目標類型T進行惰性初始化。
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
使用:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
好處就是對無法修改的目標類型進行單例化,好像也沒多大卵用。
- 枚舉方式
線程安全,性能可以,就是怪怪的。
public enum User{
INSTANCE;
}
補充
- clone和單例是沖突的
- 反射可以破壞單例,只要加一個靜態的flag來標識是否創建過對象就可以了,反射還得走構造函數。
- 反序列化:增加方法readResolve():
public Object readResolve(){
return getInstance();
}
文章列表
全站熱搜