1. 程式人生 > >設計模式之--單例模式【小白日記】

設計模式之--單例模式【小白日記】

概念

一個類有且僅有一個例項,並自行例項化向整個系統提供這個例項。

使用場景

確保某個類有且僅有一個類的例項(物件),避免產生過多的例項消耗資源,或者某些需求中,只需一個物件的情況。譬如,
IO操作或者資料庫連線類的相關物件,對效能消耗過大地操作,或者頻繁地建立和銷燬的物件,就需要考慮是否使用該模式。

特點

  1. 建構函式不對外開放,修飾符為private;
  2. 單例類的例項(物件)有且僅有一個,尤其是多執行緒中;
  3. 確保單例類物件在反序列化時不會重新構建物件;
  4. 單例類必須自己建立自己的唯一例項(通過靜態方法或者列舉返回單例類例項)。

    注意:getInstance()方法中需要使用同步鎖 synchronized (Singleton.class) 防止多執行緒同時進入造成instance被多次例項化。

優點

  1. 系統記憶體裡只有一個物件例項,降低記憶體消耗;
  2. 避免對資源的多重佔用,比如對檔案的讀寫。

缺點

  1. 沒有介面,也無法繼承;
  2. 不符合單一職責原則,一個類應該只關心內部實現邏輯,而不應該關心外部如何去例項化它;

簡單示例

public class SingletonClass {
    // 建立SingletonClass例項
    private static SingletonClass singleInstance = new SingletonClass();

    // 私有的建構函式,防止通過建構函式例項化物件
    private SingletonClass
(){} // 獲取例項 public static SingletonClass getInstance() { return singleInstance; } }

呼叫方式

public class SingletonPatternTest {
   public static void main(String[] args) {
      //獲取唯一可用的物件
      SingletonClass singletonObj = SingletonClass.getInstance();
   }
}

其他實現方式

  • 懶漢模式一

    懶漢模式是宣告一個靜態物件,並且在使用者第一次呼叫getInstance時進行初始化。這種方式是最基本的實現方式,由於沒有加同步鎖 synchronized,所以它不支援多執行緒。嚴格來講,算不上單例模式。

// 懶漢模式一,不要求執行緒安全,不適用於多執行緒中
public class SingletonClass {
    private static SingletonClass singleInstance;

    private SingletonClass(){}

    public static SingletonClass getInstance() {
        if (null == singleInstance) {
            singleInstance = new SingletonClass();
        }
        return singleInstance;
    }  
} 
  • 懶漢模式二

    此方式添加了同步鎖 synchronized,所以它能夠支援多執行緒。但是,效率很低,99% 情況下不需要同步。

// 懶漢模式二,要求執行緒安全,適用於多執行緒中
public class SingletonClass {
    private static SingletonClass singleInstance;

    private SingletonClass(){}

    public static synchronized SingletonClass getInstance() {
        if (null == singleInstance) {
            singleInstance = new SingletonClass();
        }
        return singleInstance;
    }  
} 
總結:懶漢模式的優點是單例只有在使用時才被例項化,在一定程度上節約了資源開銷;缺點是第一次載入時需要即時進行例項化,反應稍慢,
而且每次呼叫getInstance都進行同步,造成不必要的同步開銷,這種模式不推薦使用。
  • 餓漢模式

    此模式基於classloader機制避免了多執行緒的同步問題,但是,instance在載入的時候就已經例項化了,導致類裝載的方式有很多種,在單例模式中,大多數都是呼叫getInstance方法導致的,當然也不排除其他方式(或者其他靜態方法)導致類裝載。這時候初始化顯然是沒有達到懶載入的效果。

public class SingletonClass {
    private static SingletonClass singleInstance = new SingletonClass();

    private SingletonClass(){}

    public static SingletonClass getInstance() {        
        return singleInstance;
    }  
} 
總結:
    優點:沒有同步鎖,執行效率高;
    缺點:類載入時就初始化,浪費記憶體資源;
  • Double Checke Lock(DCL)雙重校驗鎖/雙檢鎖模式

    此模式採用雙鎖機制,安全且在多執行緒情況下能保持高效能。既能在需要的時才初始化單例,又能保證執行緒安全,且物件例項化後呼叫getInstance不進行同步鎖。getInstance()的效能對應用程式很關鍵。

public class SingletonClass {

    private static SingletonClass singleInstance = null;

    private SingletonClass(){}

    public static SingletonClass getInstance() {
        if (null == singleInstance) {// 避免不必要的同步
            synchronized (SingletonClass.class) {
                if (null == singleInstance) {// 在未例項化的情況下才建立例項
                    singleInstance = new SingletonClass();
                }
            }
        }

        return singleInstance;
    }  
} 
總結:
    DCL優點:資源利用率高,第一次執行getInstance時單例物件才會被初始化,效率高。

    DCL缺點:第一次載入反應稍慢,也由於Java記憶體模型的原因偶爾會失敗(Java編譯器允許處理器亂序執行程式指令,JDK1.6後修復),
    在高併發情況下也有一定的缺陷,但是發生頻率很小。

    此模式是使用最多的單例實現方式,它能夠在需要時才例項化單例物件,並且能夠在絕大多數場景中保證單例物件的唯一性,
    除非你的程式碼在併發場景比較複雜或低於JDK6版本下使用,否則,此方式一般能夠滿足需求。
  • 靜態內部類模式

    靜態內部類模式主要用於彌補DCL模式的缺陷(即DCL失效)。

public class SingletonClass {

    private SingletonClass(){}

    public static SingletonClass getInstance() {
        return SingletonHolder.singleInstance;
    }

    /** 靜態內部類 */
    private static class SingletonHolder {
        private static final SingletonClass singleInstance = new SingletonClass();
    } 
} 
總結:
    靜態內部類模式,首次載入SingletonClass類時並不會初始化singleInstance,
    只有在第一次的呼叫getInstance()方法時才會載入SingletonHolder類,這種方式不僅能夠確保執行緒安全,
    也能夠保證單例物件的唯一性,同時也延遲了單例的例項化。推薦使用的單例模式。
  • 列舉模式

    列舉模式是最簡單的單例實現方式,也是最佳的單例實現方式。簡潔,自動支援序列化機制,絕對防止多次例項化。由於 JDK1.5 之後才加入 enum 特性,用這種方式寫不免讓人感覺生疏,在實際工作中,也很少用。

public enum SingletonClass {
    INSTANCE;
    public void doSth() {
        // TO DO
    }
} 
總結:列舉單例模式的最大優點就是寫法非常簡單。列舉在Java中與普通的類一樣,不僅能夠有欄位,還能夠有自己的方法,
最重要的是預設列舉例項的建立是執行緒安全的,並且在任何情況下都是一個單例。
  • 容器模式

    容器模式,是將不同的單例物件放在Map中,通過key獲取物件對應的型別的物件。程式碼如下:

public class SingletonClass {

    private static Map<String, Object> map = new HashMap<String, Object>();

    private SingletonClass() {}

    public static void registerService(String key, Object instance) {
        if (!map.containsKey(key)) {
            map.put(key, instance);
        }
    }

    public static Object getService(String key) {
        return map.get(key);
    }
} 
總結:容器模式可以管理多種型別的單例,並且在使用時可以通過統一的介面進行獲取操作,降低使用成本,隱藏了具體實現,
降低了耦合度。

正常情況下,建議使用【餓漢模式】,如果要明確實現懶載入效果,可使用【靜態內部類模式】,如果涉及反序列化建立物件時,建議採用【列舉模式】,如果想管理多種型別的單例,可以考慮【容器模式】,特殊需求,可以試試【雙檢鎖模式】。

注:本帖子相關內容參考於網路,侵刪。

相關推薦

設計模式--模式日記

概念 一個類有且僅有一個例項,並自行例項化向整個系統提供這個例項。 使用場景 確保某個類有且僅有一個類的例項(物件),避免產生過多的例項消耗資源,或者某些需求中,只需一個物件的情況。譬如, IO操作或者資料庫連線類的相關物件,對效能消耗過大地操作,或者頻

javascriptjavascript設計模式模式

函數 設置 tin 私有 資源 公有 key fun 初始化 單例模式: 定義:單例模式之所以這麽叫,是因為它限制一個類只能有一個實例化對象。 實現方法:判斷實例是否存在,如果存在則直接返回,如果不存在就創建了再返回。(確保一個類只有一個實例對象) 特點: 命名空間提供者,

設計模式模式內附物件例項化幾種方式、實現執行緒安全幾種方式

繼續來複習常用的設計模式-單例模式,順便回憶一下執行緒安全的幾種實現方式。 一、什麼是單例模式 單例模式,簡單常用的一種設計模式,也很好的體現了程式碼控制物件在記憶體數量的一種方式,主要分2種實現方式: ①餓漢式,執行緒安全 ②懶漢式,執行緒不安全(新增鎖機制,可以實現執行緒安全)

Java如何初步掌握java設計模式模式

單例設計模式(Singleton Pattern)是最簡單且常見的設計模式之一,主要作用是提供一個全域性訪問且只例項化一次的物件,避免多例項物件的情況下引起邏輯性錯誤(例項化數量可控)… 概述 Java中,單例模式主要分三種:懶漢式單例、餓漢式單例、登記式單例三種。 特點

JAVA設計模式模式

懶漢 常見 單例 str 自己 餓漢式 span color 實例 前言 java最常見的設計模式就是單例模式,而單例模式最常見的就是懶漢式和餓漢式,現在就分別看一下 1.懶漢式 懶漢式比較懶,當別人用到時才會初始化實例,而當有多個人同時用到就可能產生多個實例,造成線程

筆記(設計模式模式),後續發現問題會進行修改,大神勿噴,謝謝。

提高效率 public code 靜態屬性 懶漢 加載 屬性 設計模式之單例模式 syn 單例模式 package com.bjsxt.thread.syn; /** * 單例創建方式 * 1.懶漢式 * 1)構造器私有化 * 2)聲明私有的靜態變量 * 3)對外

朝花夕拾設計模式模式

itl con 單個 靜態類 domain led 加載數據 簡單 領導 單例模式簡介 單例模式是GOF 23個設計模式中最簡單的模式了,它提供了一種創建唯一對象的最佳實現,註意此處的簡單只是表述和意圖很簡單,但是實現起來,尤其是實現一個優美的單例模式卻沒有那麽簡單

JAVA設計模式模式(轉)

單例對象 日誌 locking anti 常見 基本上 title 加載 懶漢式 本文繼續介紹23種設計模式系列之單例模式。 概念:  java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,這裏主要介紹三種:懶漢式單例、餓漢式單例、登記式單例。  單例模式有以下特

設計模式模式

ins 一次 初始 之間 懶加載 sin jdk1.5 代碼 tin 一、概念   Java中單例模式是一種非常常見的設計模式,單例模式確保某個類只有一個實例,而且自行實例化並向整個系統提供這個實例。 二、特點   1、單例類只有一個實例。   2、單例類必須自己創建自己的

Python設計模式模式

定義 eat size 字典 con gin 自動 super pytho 單例模式單例模式需要註意的地方在於如何保證創建的實例是唯一的如何保證多線程情況下的訪問清晰明了目前有這麽幾種方法:modulemetaclass__new__decoratormodule其實,Py

PHP設計模式模式

blog inf DDU dbn 返回 bug 面向對象 程序員 userinfo 參考:http://www.cnblogs.com/yangjinjin/archive/2013/01/31/2887492.html 李炎恢PHP第三季視頻 單例模式 單例模式確保某個類

iOS設計模式模式

trac 實例 配方 implement 字節數 bsp 變量 auto == 單例模式:總是返回自己的同一個實例,它提供了對類的對象所提供的資源的全局訪問點,而且返回的實例僅僅能被實例化一次. 單例設計模式設計須要考慮的兩個問題: (1) :發起調

理解js設計模式模式

單例 false single 這樣的 字面量 不可靠 urn 如果 == 單例模式的定義:只提供唯一的一個實例來讓你訪問 js中單例是天然存在的: var a1={ hello:‘js‘ } var a2={ hello:‘js‘ } cons

設計模式模式以及簡單代碼實現

以及 應用 安全 設計模式 div 代碼實現 測試類 加載類 實例 單例模式 保證整個應用某個實例只有一個 單例模式包括懶漢模式和餓漢模式 餓漢模式 懶漢模式 測試類 區別: 餓漢模式的特點加載類時比較慢,但運行獲取對象速度比較快 線程安全 懶漢模式加

設計模式模式 Singleton實現

-- throw return null mage demo1 nbsp 定義 所在 餓漢式 餓漢式單例模式,static變量會在類裝載時初始化,此時也不會涉及多個線程對象訪問該對象的問題。虛擬機保證只會裝載一次該類,肯定不會發生並發訪問的問題,

設計模式模式 Singleton

方式 logs 作用 內部類 內部 singleton 訪問 let 共享 核心作用 保證一個類只有一個實例,並且提供一個訪問該實例的全局訪問點。 常見應用場景 優點

Java設計模式模式

設計 return 線程安全 -s ron none 方法 有一個 ava   一、前言:   轉載需要註明出處: https://i.cnblogs.com/EditPosts.aspx?opt=1   單例模式其實很早之前就已經接觸過了,但都是為了應付面試或者是為了裝X

js設計模式模式

想要 判斷 mage blog nbsp mes new 1-1 單例 1 var xiaowang = (function(argument){ 2 var xiaowangjia = function(message){

常用設計模式模式

serial 修改 反射 類型 tile 應用場景 ray 例子 flag 單例對象(Singleton)是一種常用的設計模式。在Java應用中,單例對象能保證在一個JVM中,該對象只 有一個實例存在。這樣的模式有幾個好處: 1、某些類創建比較頻繁,對於一些大型的對象,這是

Java設計模式模式(七種寫法)

不一定 java設計 font method 防止 turn 無法 lazy 三種 Java設計模式之單例模式(七種寫法) 第一種,懶漢式,lazy初始化,線程不安全,多線程中無法工作: public class Singleton { private stati