本文實(shí)例為大家分享了Java設(shè)計(jì)模式之單例模式的具體代碼,供大家參考,具體內(nèi)容如下
概念:
單例模式:一個(gè)類中只有一個(gè)實(shí)例。
一個(gè)類有且僅有一個(gè)實(shí)例,并且提供了一個(gè)全局的訪問點(diǎn)。
使用該模式的起因:
當(dāng)我們在瀏覽網(wǎng)站時(shí),有些網(wǎng)站會顯示“當(dāng)前在線人數(shù)”。通常,實(shí)現(xiàn)這個(gè)功能的辦法是將登陸的每一個(gè)IP存儲在一個(gè)內(nèi)存、文件或者數(shù)據(jù)庫中,每多一個(gè)IP,就實(shí)現(xiàn)“+1”。一般就是用一個(gè)方法,比如add(),實(shí)現(xiàn)“+1”的功能,比如用“update”語句,先獲取數(shù)據(jù)庫中存儲的數(shù)據(jù),再+1,更新數(shù)據(jù)庫中的數(shù)據(jù),,然后保存;顯示在頁面時(shí),再通過另外的方法獲取數(shù)據(jù)庫中的數(shù)據(jù)即可。但是,當(dāng)多個(gè)用戶同時(shí)登陸時(shí),如果每一個(gè)都要new一個(gè)對象,然后再通過“對象.方法名”調(diào)用執(zhí)行add()方法,再將數(shù)據(jù)存儲到數(shù)據(jù)庫中,這樣就會導(dǎo)致多個(gè)用戶無法將實(shí)際的用戶數(shù)據(jù)準(zhǔn)確的記錄到數(shù)據(jù)庫中。所以,把這個(gè)計(jì)數(shù)器設(shè)計(jì)為一個(gè)全局對象(所有人都使用這一個(gè)對象,而不是用一個(gè),new一個(gè)),所有人都共用同一份數(shù)據(jù),就可以避免類似的問題,這就是我們所說的單例模式的其中的一種應(yīng)用。
同樣的,還有其他場景中,也會遇到相似的情景,使用到類似的思路。比如:
1.外部資源:每臺計(jì)算機(jī)有若干個(gè)打印機(jī),但只能有一個(gè)PrinterSpooler,以避免兩個(gè)打印作業(yè)同時(shí)輸出到打印機(jī)。內(nèi)部資源:大多數(shù)軟件都有一個(gè)(或多個(gè))屬性文件存放系統(tǒng)配置,這樣的系統(tǒng)應(yīng)該有一個(gè)對象管理這些屬性文件
2. Windows的Task Manager(任務(wù)管理器)就是很典型的單例模式(這個(gè)很熟悉吧),想想看,是不是呢,你能打開兩個(gè)windows task manager嗎? 不信你自己試試看哦~
3. windows的Recycle Bin(回收站)也是典型的單例應(yīng)用。在整個(gè)系統(tǒng)運(yùn)行過程中,回收站一直維護(hù)著僅有的一個(gè)實(shí)例。
4. 網(wǎng)站的計(jì)數(shù)器,一般也是采用單例模式實(shí)現(xiàn),否則難以同步。
5. 應(yīng)用程序的日志應(yīng)用,一般都何用單例模式實(shí)現(xiàn),這一般是由于共享的日志文件一直處于打開狀態(tài),因?yàn)橹荒苡幸粋€(gè)實(shí)例去操作,否則內(nèi)容不好追加。
6. Web應(yīng)用的配置對象的讀取,一般也應(yīng)用單例模式,這個(gè)是由于配置文件是共享的資源。
7. 數(shù)據(jù)庫連接池的設(shè)計(jì)一般也是采用單例模式,因?yàn)閿?shù)據(jù)庫連接是一種數(shù)據(jù)庫資源。數(shù)據(jù)庫軟件系統(tǒng)中使用數(shù)據(jù)庫連接池,主要是節(jié)省打開或者關(guān)閉數(shù)據(jù)庫連接所引起的效率損耗,這種效率上的損耗還是非常昂貴的,因?yàn)楹斡脝卫J絹砭S護(hù),就可以大大降低這種損耗。
8. 多線程的線程池的設(shè)計(jì)一般也是采用單例模式,這是由于線程池要方便對池中的線程進(jìn)行控制。
9. 操作系統(tǒng)的文件系統(tǒng),也是大的單例模式實(shí)現(xiàn)的具體例子,一個(gè)操作系統(tǒng)只能有一個(gè)文件系統(tǒng)。
10. HttpApplication 也是單位例的典型應(yīng)用。熟悉ASP.Net(IIS)的整個(gè)請求生命周期的人應(yīng)該知道HttpApplication也是單例模式,所有的HttpModule都共享一個(gè)HttpApplication實(shí)例。
總結(jié)起來,單例模式的一般應(yīng)用場景為:
1.需要頻繁實(shí)例化然后銷毀的對象。
2.創(chuàng)建對象時(shí)耗時(shí)過多或者耗資源過多,但又經(jīng)常用到的對象。
3.有狀態(tài)的工具類對象。
4.頻繁訪問數(shù)據(jù)庫或者文件的對象。
5.資源共享的情況下,避免由于資源操作時(shí)導(dǎo)致的性能或損耗等。如上述中的日志文件、應(yīng)用配置等。
6.控制資源的情況下,方便資源之間的互相通信。如線程池等。
特點(diǎn):
1、單例類只能有一個(gè)實(shí)例;
2、單例類必須自己創(chuàng)建自己的唯一實(shí)例;
3、單例類必須給所有其他對象提供這一實(shí)例
單例模式要素:
1.私有構(gòu)造方法
2.私有靜態(tài)引用指向自己實(shí)例
3.以自己實(shí)例為返回值的公有靜態(tài)方法
實(shí)現(xiàn)單例模式的三種方法:
1.餓漢式:單例實(shí)例在類裝載時(shí)就構(gòu)建,急切初始化。(預(yù)先加載法)
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * 餓漢式(推薦) * */ public class Test { private Test() { } public static Test instance = new Test(); public Test getInstance() { return instance; } } |
優(yōu)點(diǎn)
1.線程安全
2.在類加載的同時(shí)已經(jīng)創(chuàng)建好一個(gè)靜態(tài)對象,調(diào)用時(shí)反應(yīng)速度快
缺點(diǎn)
資源效率不高,可能getInstance()永遠(yuǎn)不會執(zhí)行到,但執(zhí)行該類的其他靜態(tài)方法或者加載了該類(class.forName),那么這個(gè)實(shí)例仍然初始化
2.懶漢式:單例實(shí)例在第一次被使用時(shí)構(gòu)建,延遲初始化。
1
2
3
4
5
6
7
8
9
10
11
12
|
class Test { private Test() { } public static Test instance = null ; public static Test getInstance() { if (instance == null ) { //多個(gè)線程判斷instance都為null時(shí),在執(zhí)行new操作時(shí)多線程會出現(xiàn)重復(fù)情況 instance = new Singleton2(); } return instance; } } |
優(yōu)點(diǎn)
避免了餓漢式的那種在沒有用到的情況下創(chuàng)建事例,資源利用率高,不執(zhí)行g(shù)etInstance()就不會被實(shí)例,可以執(zhí)行該類的其他靜態(tài)方法。
缺點(diǎn)
懶漢式在單個(gè)線程中沒有問題,但多個(gè)線程同事訪問的時(shí)候就可能同事創(chuàng)建多個(gè)實(shí)例,而且這多個(gè)實(shí)例不是同一個(gè)對象,雖然后面創(chuàng)建的實(shí)例會覆蓋先創(chuàng)建的實(shí)例,但是還是會存在拿到不同對象的情況。解決這個(gè)問題的辦法就是加鎖synchonized,第一次加載時(shí)不夠快,多線程使用不必要的同步開銷大。
3.雙重檢測
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Test { private Test() { } public static Test instance = null ; public static Test getInstance() { if (instance == null ) { synchronized (Test. class ) { if (instance == null ) { instance = new Test(); } } } return instance; } } |
優(yōu)點(diǎn)
資源利用率高,不執(zhí)行g(shù)etInstance()就不被實(shí)例,可以執(zhí)行該類其他靜態(tài)方法
缺點(diǎn)
第一次加載時(shí)反應(yīng)不快,由于java內(nèi)存模型一些原因偶爾失敗
4.靜態(tài)內(nèi)部類
1
2
3
4
5
6
7
8
9
10
11
12
|
class Test { private Test() { } private static class SingletonHelp { static Test instance = new Test(); } public static Test getInstance() { return SingletonHelp.instance; } } |
優(yōu)點(diǎn)
資源利用率高,不執(zhí)行g(shù)etInstance()不被實(shí)例,可以執(zhí)行該類其他靜態(tài)方法
缺點(diǎn)
第一次加載時(shí)反應(yīng)不夠快
總結(jié):
一般采用餓漢式,若對資源十分在意可以采用靜態(tài)內(nèi)部類,不建議采用懶漢式及雙重檢測
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/lishiwei/p/8035132.html