05單件模式

来源:https://www.cnblogs.com/yunshalee/archive/2023/04/18/17330643.html
-Advertisement-
Play Games

#經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實例。 // 其他有用的實例變數寫在這裡 //構造器聲明為私有,只有Singleton可以實例化這個類! ...


經典的單件模式

public class Singleton {
  private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實例。
  // 其他有用的實例變數寫在這裡

  //構造器聲明為私有,只有Singleton可以實例化這個類!
  private Singleton() ()
  
  public static Singleton getInstance(){
    if(uniqueInstance == null){
        uniqueInstance = new Singleton();//getInstance()方法提供了一種實例化該類的方式,也返回它的一個實例。
    }
    return uniqueInstance ;
  }
}

單件模式沒有公開的構造器,構造器聲明為私有;為了獲得一個單件對象,不是實例化一個,只是請求一個實例。因此類有一個靜態方法,稱為getInstance()。

用途:常常被用來管理資源池,像連接或者線程池。

你有一個包含註冊表設置的對象。你不想讓這個對象有多個副本,到處賦值一這會導致混亂。通過使用像單件模式這樣的對象,你可以確保應用中的每個對象使用同一全局資源。

例子--巧克力工廠

一個Choc-O-Hoic公司的工業強度巧克力鍋爐控制器類

public class ChocolateBoiler {
  private boolean empty;
  private boolean boiled;

  //這段代碼只有在鍋爐空的時候才啟動!
  public ChocolateBoiler(){
    empty = true;
    boiled = false;
  }

  //要往鍋爐里填充原料,鍋爐必須是空的。一旦鍋爐滿了,我們就設置empty和boiled標誌
  public void fill() {
    if(isEmpty()) {
        empty = false;
        boiled = false;
        //往鍋爐里填充牛奶/巧克力混合物
    }
  }

  //要排空鍋爐,鍋爐必須是滿的 (非空) 且煮過的。一旦排出完畢,我們把empty設置回true。
  public void drain() {
    if(!isEmpty() && isBoiled()) {
        //排出煮沸的牛奶和巧克力
        empty = true;
    }
  }

  //要煮混合物,鍋爐必須是滿而且未煮過的。一旦煮沸,我們r把boiled標誌設為true。
  public void boil() {
    if(!isEmpty() &&!isBoiled()) {
        //將爐內物煮沸
        boiled = true;
    }
  }

  public boolean isEmpty() {return empty;}
  public boolean isBoiled() (return boiled;}
}

改成單件模式

public class ChocolateBoiler {
  private boolean empty;
  private boolean boiled;

  //改動一:
  private static Chocolateboiler uniqueinatance;

  //改動二:
  private ChocolateBoiler(){
    empty = true;
    boiled = false;
  }
  //改動三:
  public static ChocolateBoiler getInstance(){
    if(uniqueInstance == null) {
      uniqueInstance = new ChocolateBoiler()
    }
    return uniqueInstance;
  }

  public void fill() {
    if(isEmpty()) {
      empty = false;
      boiled = false;
      //往鍋爐里填充牛奶/巧克力混合物
    }
  }
  // 剩下的chocolateBoiler代碼·
}

單件模式

單件模式:確保一個類只有一個實例,並提供一個全局訪問點;
類圖:

添加線程造成的問題

解決多線程:通過把getInstance()方法變成同步(Synchronized)方法;
但是同步導致性能開銷大

改進多線程

1.如果getlnstance()的性能對應用來說不是很關鍵,什麼也不做。
2.轉為急切(eagerly) 創建實例,而不用延遲創建

用這個方法,當類被載入時,我們依靠JVM來創建單件的唯一實例。JVM 保證在任何線程訪問靜態uniqueInstance變數之前,實例會被創建。

public class Singleton {
  //在靜態初始化器中創建單件實例,這段代碼保證是線程安全的!
  private static Singleton uniqueInstance = new Singleton();
  private Singleton() {}

  public static Singleton getInstance() {
    return uniqueInstance;//我們已經有了一個實例,因此返回它即可。
  }
}

3.用“雙重檢查加鎖”在getlnstance()減少使用同步
雙重檢查加鎖不適用1.4以及更早版本的Java!

public class Singleton {
  //volatile關鍵詞確保:當uniquelnstance變數被初始化為單件實例時,多個線程正確處理uniquelnstance變數
  private volatilestatic Singleton uniqueInstance;
  private Singleton() {}
  
  public static Singleton getInstance() {
    if(uniqueInstance == null) {//檢查實例,如果沒有,進入同步區塊。
       synchronized(Singleton.class){//註意,只有第一次才同步
          if(uniqueInstance == null) {
              uniqueInstance = new Singleton();//進入區塊後,再檢查一次。如果依然是空的,創建一個實例。
          }
        }
    }
    return uniqueInstance;
  }
}

總結

單件,確保一個類只有一個實例,並提供全局訪問點。
當你需要確保應用中的某個類只有一個實例,就用單件模式吧。

要點

1.單件模式確保應用中個類最多只有一個實例。
2.單件模式也提供訪問此實例的全局點。
3.Java的單件實現用了一個私有構造器、一個靜態方法以及一個靜態變數。
4.檢查你的性能和資源約束,為多線程應用小心選擇一個適當的單件實現 (我們應該把所有應用都考慮為是多線程的)。
5.提防雙重檢查加鎖實現。Java 5之前的版本,不是線程安全的
6.如果你使用多個類載入器,要小心,可能導致單件實現失效,導致出現多個實例。
7.你可以使用Java的枚舉來簡化單件的實現。


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

-Advertisement-
Play Games
更多相關文章
  • 轉載請註明 來源:http://www.eword.name/ Author:eword Email:[email protected] webpack 是什麼 Webpack 是一個前端資源載入/打包工具。它將根據模塊的依賴關係進行靜態分析,然後將這些模塊按照指定的規則生成對應的靜態資源。 從圖中我 ...
  • 好家伙, 代碼已開源 Git: https://gitee.com/tang-and-han-dynasties/panghu-planebattle-esm.git NPM: panghu-planebattle-esm - npm (npmjs.com) 現在,比如說,我用Vue寫好了個人博客主 ...
  • Vue3 的狀態管理主要是通過 Vuex 4 來實現。Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式,它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。 在Vue3的狀態管理中,以下是各個屬性的作用: state:存儲應用程式中的狀態數據。它 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 當今Web開發中,數據安全是一個至關重要的問題,為了確保數據的安全性,我們需要使用加密技術。JavaScript作為一種客戶端編程語言,可以很好地為數據進行加密。在本篇文章中,我們將為你提供一個常規JavaScript加密大全,以及案例代 ...
  • 在Vue3中,路由的基本配置是通過使用Vue Router庫來實現的。以下是Vue3中路由的基本配置步驟: 安裝Vue Router 使用npm或yarn在項目中安裝Vue Router: npm install vue-router // 或者 yarn add vue-router 創建路由實例 ...
  • 在Vue3中,計算屬性可以使用computed函數來定義。 computed函數接受兩個參數:第一個參數是一個函數,該函數返回計算屬性的值;第二個參數是一個可選的配置對象,可以包含getter和setter函數,以及控制計算屬性緩存的緩存配置。 Vue3中的計算屬性與Vue2中的計算屬性相比有以下幾 ...
  • 拉去遠程分支代碼報錯:fatal: refusing to merge unrelated histories造成的原因是: 1、本地項目copy 其他項目的結構把.git 文件可拷貝過來了 且覆蓋了自己當前目錄的 .git 文件,然後將當前分支合遠程分支合併 因為兩個 .git 文件儲存庫的歷史數 ...
  • 後臺管理系統在實際開發中,表格如果在一定高度出現滾動條。 這時如果對錶格行數據進行編輯或者拖拽排序操作,數據刷新後滾動條會預設回到頂部,這樣體驗會不太好。 如果想保留在當前位置可以這樣操作: 1.el-table標簽添加ref屬性 <el-table :data="tableData" v-load ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...