設(shè)計模式-單例模式
定義
單例模式(singleton pattern)是確保一個類在任何情況下都絕對只有一個實例勉吻,并提供一個全局訪問點旅赢。
單例模式是創(chuàng)建型模式齿桃。
分類
1、餓漢式(餓漢和靜態(tài)餓漢)
2带污、懶漢式(線程安全要加鎖)
3香到、枚舉式(注冊)初始化即生成,餓漢式养渴,可以保證不被反射機(jī)制和反序列化破壞,是借助JDK的特性翘紊,所以最官方藐唠、最權(quán)威、最穩(wěn)定
4踪宠、序列化單例模式(可以解決反序列化問題妈嘹,但是內(nèi)存開銷依然很大)
5、容器式單例模式(容器式單例模式適用于需要大量創(chuàng)建單例對象的場景润脸,便于管理毙驯。但它是非線程安全的)
6、threadLocal單例模式(不能保證其創(chuàng)建的對象是全局唯一的爆价,但是能保證在單個線程中是唯一的,天生是線程安全的)
總結(jié)
????單例模式可以保證內(nèi)存中只有一個實例骤宣,減少了內(nèi)存開銷序愚,還可以避免對資源的多重占用。
單例模式的常見應(yīng)?場景
單例模式(Singleton)也叫單態(tài)模式活逆,是設(shè)計模式中最為簡單的?種模式拗胜,甚?有些模式?師都不稱其為模式,稱其為?種實現(xiàn)技巧锈遥,因為設(shè)計模式講究對象之間的關(guān)系的抽象勘畔,?單例模式只有???個對象,也因此有些設(shè)計?師并把把其稱為設(shè)計模式之?炫七。
好多沒怎么使?過的?可能會想万哪,單例模式感覺不怎么?到,實際的應(yīng)?場景有哪些呢奕巍?以下,我將列出?些就在咱們周邊和很有意義的單例應(yīng)?場景檩坚。
1. Windows的Task Manager(任務(wù)管理器)就是很典型的單例模式(這個很熟悉吧)诅福,想想看,是不是呢剩檀,你能打開兩個windows task manager嗎旺芽? 不信你??試試看哦~
2. windows的Recycle Bin(回收站)也是典型的單例應(yīng)?。在整個系統(tǒng)運?過程中运嗜,回收站?直維護(hù)著僅有的?個實例悯舟。
3. ?站的計數(shù)器,?般也是采?單例模式實現(xiàn)抵怎,否則難以同步。
4. 應(yīng)?程序的?志應(yīng)?尝艘,?般都何?單例模式實現(xiàn),這?般是由于共享的?志?件?直處于打開狀態(tài)秒际,因為只能有?個實例去操作狡汉,否則內(nèi)容不好追加。
5. Web應(yīng)?的配置對象的讀取寄锐,?般也應(yīng)?單例模式捻脖,這個是由于配置?件是共享的資源。
6. 數(shù)據(jù)庫連接池的設(shè)計?般也是采?單例模式沿癞,因為數(shù)據(jù)庫連接是?種數(shù)據(jù)庫資源矛渴。數(shù)據(jù)庫軟件系統(tǒng)中使?數(shù)據(jù)庫連接池,主要是節(jié)省打開或者關(guān)閉數(shù)據(jù)庫連接所引起的效率損耗蚕涤,這種效率上的損耗還是?常昂貴的铣猩,因為何?單例模式來維護(hù),就可以??降低這種損耗达皿。
7. 多線程的線程池的設(shè)計?般也是采?單例模式,這是由于線程池要?便對池中的線程進(jìn)?控制龄寞。
8. 操作系統(tǒng)的?件系統(tǒng)汤功,也是?的單例模式實現(xiàn)的具體例?,?個操作系統(tǒng)只能有?個?件系統(tǒng)色解。
9. HttpApplication 也是單位例的典型應(yīng)?。熟悉ASP.Net(IIS)的整個請求?命周期的?應(yīng)該知道HttpApplication也是單例模式在抛,所有的HttpModule都共享?個HttpApplication實例.
? 總結(jié)以上萧恕,不難看出:
單例模式應(yīng)?的場景?般發(fā)現(xiàn)在以下條件下:
(1)資源共享的情況下肠阱,避免由于資源操作時導(dǎo)致的性能或損耗等。如上述中的?志?件走趋,應(yīng)?配置噪伊。
(2)控制資源的情況下,?便資源之間的互相通信姨伟。如線程池等豆励。
單例模式優(yōu)點:
1、在內(nèi)存中只有一個實例技扼,減少了內(nèi)存開銷嫩痰。
2、可以避免資源的多重占用串纺。
3造垛、設(shè)置全局訪問點,嚴(yán)格控制訪問五辽。
單例模式的缺點:
1、沒有接口乡翅,擴(kuò)展困難。
2尚洽、如果要擴(kuò)展單例對象靶累,只有修改代碼,沒有其他途徑潮酒。
代碼實例
學(xué)習(xí)單例模式的知識重點總結(jié)
1、私有化構(gòu)造器
2站楚、保證線程安全
單例模式可以保證內(nèi)存里只有一個實例搏嗡,減少了內(nèi)存的開銷,還可以避免對資源的多重占用。單例模式看起來非常簡單舅踪,實現(xiàn)起來其實也非常簡單良蛮,但是在面試中卻是一個高頻面試點。希望“小伙伴們”通過本章的學(xué)習(xí)货徙,對單例模式有了非常深刻的認(rèn)識皮胡,在面試中彰顯技術(shù)深度,提升核心競爭力蠢棱,給面試加分甩栈,順利拿到錄取通知(Offer)。
擴(kuò)展
1量没、解決容器式單例的線程安全問題殴蹄。
兩種方法:雙重檢查鎖,利用ConcurrentHashMap#putIfAbsent()方法的原子性袭灯。
public class ContainerSingleton {
????private static Map ioc = new ConcurrentHashMap();
????private ContainerSingleton() {
? ? ? ? ????throw new RuntimeException("不可被實例化稽荧!");
????}
? ? // 方法一:雙重檢查鎖
????public static Object getInstance(String className) {
????????Object instance = null;
????????if (!ioc.containsKey(className)) {
????????????synchronized (ContainerSingleton.class) {
????????????????if (!ioc.containsKey(className)) {
????????????????????try {
????????????????????????instance = Class.forName(className).newInstance();
????????????????????????ioc.put(className, instance);
? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
????????????????????????e.printStackTrace();
????????????????????}
????????????????return instance;
????????????????} else {
????????????????????return ioc.get(className);
????????????????}
????????????}
????????}
????????return ioc.get(className);
????}
? ? // 方法二:利用ConcurrentHashMap#putIfAbsent()方法的原子性
public static Object getInstance1(String className){
????Object instance = null;
????try {
????????ioc.putIfAbsent(className, Class.forName(className).newInstance());
????}catch (Exception e){
????????e.printStackTrace();
????}
????return ioc.get(className);
????}
}