1.餓漢式
類(lèi)加載的時(shí)候就會(huì)初始化,他是線(xiàn)程安全的,但是類(lèi)加載的時(shí)候就初始化這樣會(huì)預(yù)先消耗一部分資源。
/**
* Created by lijiayi on 2017/3/1.
* 餓漢式單例
*/
public class Singleton {
//生成單例對(duì)象
private static final Singleton mSingleton = new Singleton();
//私有化構(gòu)造方法
private Singleton() {
}
//獲取單例對(duì)象
public static Singleton getInstance() {
return mSingleton;
}
}
2.懶漢式
當(dāng)?shù)谝淮问褂玫臅r(shí)候才創(chuàng)建對(duì)象,合理占用資源,但是當(dāng)該對(duì)象已經(jīng)創(chuàng)建的時(shí)候,調(diào)用getInstance()方法會(huì)產(chǎn)生不必要的開(kāi)銷(xiāo),這是懶漢式的一個(gè)缺點(diǎn)。
/**
* Created by lijiayi on 2017/3/1.
* 懶漢式單例
*/
public class Singleton {
//聲明單例對(duì)象
private static Singleton mSingleton;
//私有化構(gòu)造方法
private Singleton() {
}
//同步該方法獲取單例對(duì)象
public static synchronized Singleton getInstance() {
//當(dāng)該對(duì)象為空的時(shí)候創(chuàng)建該對(duì)象
if (mSingleton == null) {
mSingleton = new Singleton();
}
//返回該對(duì)象實(shí)例
return mSingleton;
}
}
3.DCL式
該方式能保證在需要的時(shí)候才初始化單例,又能夠保證線(xiàn)程安全,而且單例初始化后調(diào)用getInstance()不會(huì)進(jìn)行同步鎖。
/**
* Created by lijiayi on 2017/3/1.
* DCL單例
*/
public class Singleton {
//聲明單例對(duì)象
private static Singleton mSingleton;
//私有化構(gòu)造方法
private Singleton() {
}
//同步該方法獲取單例對(duì)象
public static synchronized Singleton getInstance() {
//當(dāng)該對(duì)象為空的時(shí)候先同步這個(gè)對(duì)象
if (mSingleton == null) {
synchronized (Singleton.class) {
//再判斷是否為空
if (mSingleton == null) {
//如果還空的話(huà) 就創(chuàng)建對(duì)象
mSingleton = new Singleton();
}
}
}
//返回該對(duì)象實(shí)例
return mSingleton;
}
}
4.靜態(tài)內(nèi)部類(lèi)式
該方式保證了資源預(yù)先消耗、不必要的同步、線(xiàn)程的安全問(wèn)題,還避免了DCL模式在某些情況下失效的問(wèn)題。所以筆者建議使用該單例模式。
/**
* Created by lijiayi on 2017/3/1.
* 靜態(tài)內(nèi)部類(lèi)單例
*/
public class Singleton {
//私有化構(gòu)造方法
private Singleton() {
}
//獲取單例對(duì)象
public static Singleton getInstance() {
//返回內(nèi)部類(lèi)中的singleton對(duì)象
return SingletonHolder.singleton;
}
/**
* 靜態(tài)內(nèi)部類(lèi)
* 第一次加載類(lèi)的時(shí)候不用調(diào)用該類(lèi),創(chuàng)建singleton對(duì)象,
* 只有調(diào)用getInstance()方法時(shí)才會(huì)創(chuàng)建該對(duì)象。
*/
private static class SingletonHolder {
private static final Singleton singleton = new Singleton();
}
}
5.枚舉式
枚舉是線(xiàn)程安全的,而且任何情況下都是一個(gè)實(shí)例,他不能被序列化,也不能被反射,所以枚舉單例也是一個(gè)不錯(cuò)的選擇。
/**
* Created by lijiayi on 2017/3/1.
* 枚舉式單例
* 枚舉單例時(shí)線(xiàn)程安全的,在任何情況下都是一個(gè)單例
*/
public enum SingletonEnum {
//枚舉的類(lèi)型
INSTANCE;
// 單例中的函數(shù)
public void todoSomethings() {
System.out.println("do somethings");
}
}
//枚舉單例的使用
SingletonEnum.INSTANCE.todoSomethings();```
***
###6.容器實(shí)現(xiàn)單例
它的好處是可以統(tǒng)一的管理單例,安卓中g(shù)etSystemService(String name)就是用這種方式實(shí)現(xiàn)的。
``` java
/**
* Created by lijiayi on 2017/3/1.
* 容器模式單例
* 實(shí)現(xiàn)了程序中單例的統(tǒng)一管理
*/
public class SingletonManager {
private static Map<String, Object> singletonManagerMap = new HashMap<String, Object>();
//私有化構(gòu)造方法
private SingletonManager() {
}
//注入程序中的單例
public static void registerSingleton(String key, Object instance) {
if (!singletonManagerMap.containsKey(key)) {
singletonManagerMap.put(key, instance);
}
}
//獲取對(duì)于key值的單例對(duì)象
public static Object getInstance(String key) {
return singletonManagerMap.get(key);
}
}