目錄
一、基礎(chǔ)概念
二、UML類圖
三、角色設(shè)計(jì)
四、案例分析
4.1、餓漢模式
4.2、懶漢模式(線程不安全)
4.3、懶漢模式(線程安全)
4.4、雙重檢索模式
4.5、靜態(tài)內(nèi)部類
4.6、枚舉?
五、總結(jié)
一、基礎(chǔ)概念
單例模式確保一個(gè)類只有一個(gè)實(shí)例,提供一個(gè)全局訪問點(diǎn)。一般實(shí)現(xiàn)方式是把構(gòu)造函數(shù)設(shè)為私有,并提供一個(gè)靜態(tài)方法獲取實(shí)例對(duì)象。
二、UML類圖
三、角色設(shè)計(jì)
角色 | 描述 |
---|---|
單例 | 在單例類的內(nèi)部實(shí)現(xiàn)只生成一個(gè)實(shí)例,同時(shí)它提供一個(gè)靜態(tài)的 getInstance()方法,讓外部以訪問它的唯一實(shí)例;為了防止在外部對(duì)其實(shí)例化,將其構(gòu)造函數(shù)設(shè)計(jì)為私有;在單例類內(nèi)部定義了一個(gè) Singleton類型的靜態(tài)對(duì)象,作為外部共享的唯一實(shí)例。 |
四、案例分析
4.1、餓漢模式
直接在類內(nèi)部創(chuàng)建一個(gè)靜態(tài)final常量實(shí)例,線程安全,調(diào)用效率高,但無法延遲加載。
public class Singleton_Hungry {
/**
* 私有實(shí)例,靜態(tài)變量會(huì)在類加載的時(shí)候初始化,是線程安全的
*/
private static final Singleton_Hungry instance = new Singleton_Hungry();
/**
* 私有構(gòu)造方法
*/
private Singleton_Hungry() {
}
/**
* 獲取實(shí)例的方法
*/
public static Singleton_Hungry getInstance() {
return instance;
}
}
4.2、懶漢模式(線程不安全)
起初沒有實(shí)例,第一次調(diào)用才初始化,線程不安全,需加鎖處理。
public class Singleton_Lazy {
/**
* 私有實(shí)例
*/
private static Singleton_Lazy instance;
/**
* 私有構(gòu)造方法
*/
private Singleton_Lazy() {
}
/**
* 獲取實(shí)例的方法
*/
public static Singleton_Lazy getInstance() {
if (instance == null) {
instance = new Singleton_Lazy();
}
return instance;
}
}
4.3、懶漢模式(線程安全)
加鎖處理,線程安全但影響效率,大部分情況下不需要同步。
public class Singleton_Lazy_Safe {
/**
* 私有實(shí)例
*/
private static Singleton_Lazy_Safe instance;
/**
* 私有構(gòu)造方法
*/
private Singleton_Lazy_Safe () {
}
/**
* 獲取實(shí)例的方法,該方法使用synchronized加鎖,來保證線程安全性
*/
public static synchronized Singleton_Lazy_Safe getInstance() {
if (instance == null) {
instance = new Singleton_Lazy_Safe ();
}
return instance;
}
}
4.4、雙重檢索模式
雙重檢查鎖單例模式是在懶漢式單例模式的基礎(chǔ)上,額外加鎖保證多線程安全,同時(shí)保證效率,并且加入了第二次判斷,避免多線程下創(chuàng)建多個(gè)實(shí)例。
public class Singleton_Lazy_Double {
//用volatile關(guān)鍵字確保 instance 在多線程下的可見性
private static volatile Singleton_Lazy_Double instance = null;
//將構(gòu)造方法私有化,禁止外部通過構(gòu)造方法創(chuàng)建實(shí)例
private Singleton_Lazy_Double() {}
//提供一個(gè)公共的訪問方法,用于獲取該類的唯一實(shí)例
public static Singleton_Lazy_Double getInstance() {
//如果instance為空,就進(jìn)行實(shí)例化
if (instance == null) {
//保證多線程下只有一個(gè)線程進(jìn)行實(shí)例化
synchronized (Singleton_Lazy_Double.class) {
//第二次判斷,避免多線程下創(chuàng)建多個(gè)實(shí)例
if (instance == null) {
instance = new Singleton_Lazy_Double();
}
}
}
return instance;
}
}
4.5、靜態(tài)內(nèi)部類
靜態(tài)內(nèi)部類單例模式是在類加載時(shí)會(huì)創(chuàng)建一個(gè)靜態(tài)內(nèi)部類,調(diào)用getInstance方法時(shí)才會(huì)去加載該內(nèi)部類并初始化INSTANCE實(shí)例。該方式既保證了線程安全,也保證了懶加載和高效訪問的特性。
public class SingletonStatic {
/**
* 私有構(gòu)造方法
*/
private SingletonStatic() {
}
/**
* 取實(shí)例的方法
*/
public static SingletonStatic getInstance() {
return LazyHolder.INSTANCE;
}
/**
* 私有靜態(tài)內(nèi)部類
*/
private static class LazyHolder {
private static final SingletonStatic INSTANCE = new SingletonStatic();
}
}
4.6、枚舉?
使用枚舉實(shí)現(xiàn)單例模式可以節(jié)省大量代碼,并且防止多線程安全以及反序列化及反射攻擊的問題。
public enum SingletonEnum {
INSTANCE;
public void test() {
System.out.println("hello");
}
}
五、總結(jié)
優(yōu)點(diǎn):
1、在內(nèi)存中只有一個(gè)實(shí)例,減少內(nèi)存開銷。避免對(duì)資源的多重占用。設(shè)置全局訪問點(diǎn),嚴(yán)格控制訪問。
缺點(diǎn):
1、不符合單一職責(zé)原則。擴(kuò)展困難,如果要擴(kuò)展需要修改源代碼。攻擊者可通過反射和反序列化的方式獲取實(shí)例而破壞單例。
應(yīng)用場(chǎng)景:
1、需要頻繁實(shí)例化然后銷毀的對(duì)象、創(chuàng)建對(duì)象時(shí)消耗資源過多的情況等。
2、單例模式應(yīng)用在工具類、線程池、配置類、對(duì)話框、日志對(duì)象、緩存等場(chǎng)景中,在工具類中應(yīng)用是最為典型的。
符合的設(shè)計(jì)原則:
1、單一職責(zé)原則(Single Responsibility Principle)
單例類只負(fù)責(zé)創(chuàng)建自己的一個(gè)實(shí)例,有且只有這一個(gè)職責(zé)。
2、開閉原則(Open Closed Principle)
單例類可以通過擴(kuò)展改變內(nèi)部實(shí)現(xiàn)邏輯,而不影響調(diào)用端。
3、里氏替換原則(Liskov Substitution Principle)
單例類一般會(huì)實(shí)現(xiàn)一個(gè)接口定義方法,任何擴(kuò)展的實(shí)現(xiàn)會(huì)保持一致性。
4、依賴倒轉(zhuǎn)原則(Dependency Inversion Principle)
調(diào)用端通過接口依賴單例,不依賴具體實(shí)現(xiàn),降低了依賴度。
5、接口隔離原則(Interface Segregation Principle)
單例類只定義獲取實(shí)例的接口,符合接口隔離原則。
枚舉實(shí)現(xiàn)單例最大優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單,天生線程安全,防反射攻擊,是首選方式。文章來源:http://www.zghlxwxcb.cn/news/detail-546980.html
總的來說,以上各種實(shí)現(xiàn)方式之間存在效率、線程安全、懶加載等方面的權(quán)衡和區(qū)別,應(yīng)根據(jù)需要選用最合適的單例模式實(shí)現(xiàn)。文章來源地址http://www.zghlxwxcb.cn/news/detail-546980.html
到了這里,關(guān)于Java設(shè)計(jì)模式之創(chuàng)建型-單例模式(UML類圖+案例分析)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!