單例模式,是一種常用的軟件設(shè)計(jì)模式。在它的核心結(jié)構(gòu)中只包含一個(gè)被稱為單例的特殊類。通過單例模式可以保證系統(tǒng)中,應(yīng)用該模式的一個(gè)類只有一個(gè)實(shí)例。即一個(gè)類只有一個(gè)對象實(shí)例。
- 單例類只能有一個(gè)實(shí)例。
- 單例類必須自己創(chuàng)建自己的唯一實(shí)例。
- 單例類必須給所有其他對象提供這一實(shí)例。
懶漢式
當(dāng)?shù)谝淮握{(diào)用的時(shí)候才會創(chuàng)建對象,合理占用資源。
/**
* 懶漢式(線程安全)
*/
public class Singleton01 {
private static Singleton01 singleton01;
// 私有構(gòu)造方法
private Singleton01() {
}
// 同步獲取單例對象,保證線程安全
public static synchronized Singleton01 getInstance() {
// 單例對象為空的時(shí)候,創(chuàng)建單例對象
if (singleton01 == null) {
singleton01 = new Singleton01();
}
return singleton01;
}
}
餓漢式
類加載的時(shí)候就會初始化,他是線程安全的,但是類加載的時(shí)候就會初始化會預(yù)先消耗一部分資源。
/**
* 餓漢式
*/
public class SingleTon02 {
private static SingleTon02 singleTon02 = new SingleTon02();
// 私有構(gòu)造方法
private SingleTon02() {
}
public static SingleTon02 getInstance() {
return singleTon02;
}
}
雙檢索式
該方式能保證需要的時(shí)候才初始化單例,還能保證線程安全,而且單例初始化的時(shí)候調(diào)用getInstance()不會進(jìn)行同步鎖。
/**
* 雙檢索(DCL式).
*/
public class Singleton03 {
private volatile static Singleton03 singleton03;
// 私有構(gòu)造方法
private Singleton03() {
}
// 同步該方法獲取單例對象
public static Singleton03 getInstance() {
// 但對象為空時(shí)同步這個(gè)方法
if (singleton03 == null) {
synchronized (Singleton03.class) {
// 再判斷是否為空
if (singleton03 == null) {
// 為空的話就創(chuàng)建對象
singleton03 = new Singleton03();
}
}
}
return singleton03;
}
}
靜態(tài)內(nèi)部類
內(nèi)部類只有在getInstance()方法第一次調(diào)用的時(shí)候才會被加載(實(shí)現(xiàn)了延遲加載效果),而且其加載過程是線程安全的(實(shí)現(xiàn)線程安全)。內(nèi)部類加載的時(shí)候只實(shí)例化了一次instance
/**
* 靜態(tài)內(nèi)部類,推薦該該方式實(shí)現(xiàn)單例模式.
*/
public class Singleton04 {
// 私有化構(gòu)造方法
private Singleton04() {
}
/**
* 靜態(tài)內(nèi)部類.
* 內(nèi)部類只有在getInstance()方法第一次調(diào)用的時(shí)候才會被加載(實(shí)現(xiàn)了延遲加載效果),
* 而且其加載過程是線程安全的(實(shí)現(xiàn)線程安全)。內(nèi)部類加載的時(shí)候只實(shí)例化了一次instance
*/
private static class Singleton05inner {
public static final Singleton04 INSTANCE = new Singleton04();
}
public static Singleton04 getInstance() {
return Singleton05inner.INSTANCE;
}
}
枚舉
枚舉是線程安全的,而且任何情況下都是一個(gè)實(shí)例,枚舉不能實(shí)例化,不能被反射。
/**
* 枚舉.
*/
public enum Singleton05 {
INSTACNE;
public static Singleton05 getInstacne() {
return INSTACNE;
}
}
容器實(shí)現(xiàn)單例
容器實(shí)現(xiàn)單例,它的好處是可以統(tǒng)一管理單例。
/**
* 容器實(shí)現(xiàn)單例.
* 它的好處是可以統(tǒng)一的管理單例,安卓中g(shù)etSystemService(String name)就是用這種方式實(shí)現(xiàn)的.
*/
public class Singleton06 {
private static Map<String, Object> singletonManagerMap = new HashMap<>();
// 私有構(gòu)造方法
private Singleton06() {
}
// 注入程序中的單例
public static void registerSingleton(String key, Object instance) {
if (!singletonManagerMap.containsKey(key)) {
singletonManagerMap.put(key, instance);
}
}
// 獲取key值對應(yīng)的單例對象
public static Object getInstance(String key) {
return singletonManagerMap.get(key);
}
}
參考文獻(xiàn) http://www.itdecent.cn/p/8fe210e6aeb9