Java 設計模式之單例模式

来源:http://www.cnblogs.com/lishiwei/archive/2017/12/13/8035132.html
-Advertisement-
Play Games

概念: 單例模式:一個類中只有一個實例。 一個類有且僅有一個實例,並且提供了一個全局的訪問點。 使用該模式的起因: 當我們在瀏覽網站時,有些網站會顯示“當前線上人數”。通常,實現這個功能的辦法是將登陸的每一個IP存儲在一個記憶體、文件或者資料庫中,每多一個IP,就實現“+1”。一般就是用一個方法,比如 ...


概念:

單例模式:一個類中只有一個實例。

一個類有且僅有一個實例,並且提供了一個全局的訪問點。

使用該模式的起因:

  當我們在瀏覽網站時,有些網站會顯示“當前線上人數”。通常,實現這個功能的辦法是將登陸的每一個IP存儲在一個記憶體、文件或者資料庫中,每多一個IP,就實現“+1”。一般就是用一個方法,比如add(),實現“+1”的功能,比如用“update”語句,先獲取資料庫中存儲的數據,再+1,更新資料庫中的數據,,然後保存;顯示在頁面時,再通過另外的方法獲取資料庫中的數據即可。但是,當多個用戶同時登陸時,如果每一個都要new一個對象,然後再通過“對象.方法名”調用執行add()方法,再將數據存儲到資料庫中,這樣就會導致多個用戶無法將實際的用戶數據準確的記錄到資料庫中。所以,把這個計數器設計為一個全局對象(所有人都使用這一個對象,而不是用一個,new一個),所有人都共用同一份數據,就可以避免類似的問題,這就是我們所說的單例模式的其中的一種應用。

 

同樣的,還有其他場景中,也會遇到相似的情景,使用到類似的思路。比如:

   1.外部資源:每台電腦有若幹個印表機,但只能有一個PrinterSpooler,以避免兩個列印作業同時輸出到印表機。內部資源:大多數軟體都有一個(或多個)屬性文件存放系統配置,這樣的系統應該有一個對象管理這些屬性文件 
   2. Windows的Task Manager(任務管理器)就是很典型的單例模式(這個很熟悉吧),想想看,是不是呢,你能打開兩個windows task manager嗎? 不信你自己試試看哦~ 
   3. windows的Recycle Bin(回收站)也是典型的單例應用。在整個系統運行過程中,回收站一直維護著僅有的一個實例。 
   4. 網站的計數器,一般也是採用單例模式實現,否則難以同步。 
   5. 應用程式的日誌應用,一般都何用單例模式實現,這一般是由於共用的日誌文件一直處於打開狀態,因為只能有一個實例去操作,否則內容不好追加。 
   6. Web應用的配置對象的讀取,一般也應用單例模式,這個是由於配置文件是共用的資源。 
   7. 資料庫連接池的設計一般也是採用單例模式,因為資料庫連接是一種資料庫資源。資料庫軟體系統中使用資料庫連接池,主要是節省打開或者關閉資料庫連接所引起的效率損耗,這種效率上的損耗還是非常昂貴的,因為何用單例模式來維護,就可以大大降低這種損耗。 
   8. 多線程的線程池的設計一般也是採用單例模式,這是由於線程池要方便對池中的線程進行控制。 
   9. 操作系統的文件系統,也是大的單例模式實現的具體例子,一個操作系統只能有一個文件系統。 
   10. HttpApplication 也是單位例的典型應用。熟悉ASP.Net(IIS)的整個請求生命周期的人應該知道HttpApplication也是單例模式,所有的HttpModule都共用一個HttpApplication實例。

 

總結起來,單例模式的一般應用場景為:

    1.需要頻繁實例化然後銷毀的對象。

    2.創建對象時耗時過多或者耗資源過多,但又經常用到的對象。

    3.有狀態的工具類對象。

    4.頻繁訪問資料庫或者文件的對象。

    5.資源共用的情況下,避免由於資源操作時導致的性能或損耗等。如上述中的日誌文件、應用配置等。

    6.控制資源的情況下,方便資源之間的互相通信。如線程池等。

 

特點:

1、單例類只能有一個實例;

2、單例類必須自己創建自己的唯一實例;

3、單例類必須給所有其他對象提供這一實例

 

單例模式要素: 
   1.私有構造方法 
   2.私有靜態引用指向自己實例 
   3.以自己實例為返回值的公有靜態方法

 

實現單例模式的三種方法:

1.餓漢式:單例實例在類裝載時就構建,急切初始化。(預先載入法) 

/**
* 餓漢式(推薦)
*
*/
public class Test {
        private Test() {
        }
        public static Test instance = new Test();
        public Test getInstance() {
                return instance;
        }
}


優點 
    1.線程安全 
    2.在類載入的同時已經創建好一個靜態對象,調用時反應速度快 
缺點 
    資源效率不高,可能getInstance()永遠不會執行到,但執行該類的其他靜態方法或者載入了該類(class.forName),那麼這個實例仍然初始化 


2.懶漢式:單例實例在第一次被使用時構建,延遲初始化。 

class Test {
        private Test() {
        }
        public static Test instance = null;
        public static Test getInstance() {
                if (instance == null) {
              //多個線程判斷instance都為null時,在執行new操作時多線程會出現重覆情況
                        instance = new Singleton2();
                }
                return instance;
        }
}


優點 
    避免了餓漢式的那種在沒有用到的情況下創建事例,資源利用率高,不執行getInstance()就不會被實例,可以執行該類的其他靜態方法。 
缺點 
    懶漢式在單個線程中沒有問題,但多個線程同事訪問的時候就可能同事創建多個實例,而且這多個實例不是同一個對象,雖然後面創建的實例會覆蓋先創建的實例,但是還是會存在拿到不同對象的情況。解決這個問題的辦法就是加鎖synchonized,第一次載入時不夠快,多線程使用不必要的同步開銷大。 

3.雙重檢測 

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;
        }
}


優點 
    資源利用率高,不執行getInstance()就不被實例,可以執行該類其他靜態方法 
缺點 
    第一次載入時反應不快,由於java記憶體模型一些原因偶爾失敗 


4.靜態內部類 

class Test {
        private Test() {
        }

        private static class SingletonHelp {
                static Test instance = new Test();
        }

        public static Test getInstance() {
                return SingletonHelp.instance;
        }
}


優點 
    資源利用率高,不執行getInstance()不被實例,可以執行該類其他靜態方法 
缺點 
    第一次載入時反應不夠快 

總結: 
    一般採用餓漢式,若對資源十分在意可以採用靜態內部類,不建議採用懶漢式及雙重檢測 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天看到一個關於foo的一個面試題,趕腳特別有意思 ...
  • 1. 寫在前面 往常都是利用 Python/.NET 語言實現爬蟲,然現在作為一名前端開發人員,自然需要熟練 NodeJS。下麵利用 NodeJS 語言實現一個糗事百科的爬蟲。另外,本文使用的部分代碼是 es6 語法。 實現該爬蟲所需要的依賴庫如下。 1. request: 利用 get 或者 po ...
  • 前兩天有一個原來的同事問我文字描邊怎麼做,那麼今天我們就來說說文字描邊這個樣式怎麼實現. 一.文字描邊 -webkit-text-stroke 文字描邊 參數:參數1 描邊大小 參數2 描邊顏色 註意: webkit內核有效 只能使用在谷歌 ,safir有效 二.實例 上圖的效果我們怎樣來實現呢? ...
  • validateSchema模塊 首先來看錯誤檢測: 可以註意到,這裡傳了兩個參數,其實第一個參數來源於一個JSON文件: 這個JSON文件非常大,可以觀察一下部分內容: 從描述可以猜測,這裡的key對應options中的key,value就是檢測方式。 比如說entry放到required代表是必 ...
  • [1]代理模式結構 [2]圖片預載入 [3]單一職責原則 [4]合併HTTP請求 [5]虛擬代理在惰性載入中的應用 [6]緩存代理 [7]動態創建代理 [8]其他代理模式 ...
  • ul li { position:relative; display: table; width:3rem; height:3rem; background:url('image/defaultBg.jpg') 0 0/100% 100% no-repeat; float:le... ...
  • 1、概述 Iterator 的作用有三個:一是為各種數據結構,提供一個統一的、簡便的訪問介面;二是使得數據結構的成員能夠按某種次序排列;三是 ES6 創造了一種新的遍歷命令for...of迴圈,Iterator 介面主要供for...of迴圈。 2、Iterator 介面 ES6 的有些數據結構原生 ...
  • 問題描述:在vue項目中運行npm run dev啟動伺服器,然而在同一個區域網下的外部設備不能該伺服器 解決方案:在項目的config文件夾下找到index .js中的host把預設的localhost更改為0.0.0.0, 然後外部設備就可以訪問該項目啟動的服務了(註意必須是在統一區域網下) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...