日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

设计模式(2)--Singleton(单例模式)--创建型

發布時間:2024/4/15 asp.net 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设计模式(2)--Singleton(单例模式)--创建型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.模式定義:

單例模式確保一個類只有一個實例,而且自行實例化并向整個系統提供這個實例。

2.模式特點:

(1)單例類只能有一個實例。 (2)單例類必須自己創建自己的唯一實例。 (3)單例類必須給所有其他對象提供這一實例。

3.使用場景:

定義一個全局變量可以確保對象隨時都可以被訪問,但不能防止我們實例化多個對象。一個更好的解決辦法是讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例被創建,并且它可以提供一個訪問該實例的方法。這就是單例模式的模式動機。 (1)需要頻繁實例化然后銷毀的對象。 (2)創建對象時耗時過多或者耗資源過多,但又經常用到的對象。 (3)有狀態的工具類對象。 (4)頻繁訪問數據庫或文件的對象。 (5)以及其他我沒用過的所有要求只有一個對象的場景。

4.模式實現(八種方式):

  (1)餓漢式(靜態常量)[可用]

public class Singleton {

  private final static Singleton INSTANCE = new Singleton();
  private Singleton(){}
  public static Singleton getInstance(){
    return INSTANCE;
  }
} 優點:這種寫法比較簡單,就是在類裝載的時候就完成實例化。避免了線程同步問題。 缺點:在類裝載的時候就完成實例化,沒有達到Lazy Loading的效果。如果從始至終從未使用過這個實例,則會造成內存的浪費。

  (2)餓漢式(靜態代碼塊)[可用]

public class Singleton {
  private static Singleton instance;
  static {
    instance = new Singleton();
  }
  private Singleton() {}
  public Singleton getInstance() {
    return instance;
  }
} 這種方式和上面的方式其實類似,只不過將類實例化的過程放在了靜態代碼塊中,也是在類裝載的時候,就執行靜態代碼塊中的代碼,初始化類的實例。優缺點和上面是一樣的。

  (3)懶漢式(線程不安全)[不可用]

public class Singleton {
  private static Singleton singleton;
  private Singleton() {}
  public static Singleton getInstance() {
    if (singleton == null) {
      singleton = new Singleton();
    }
    return singleton;
  }
} 這種寫法起到了Lazy Loading的效果,但是只能在單線程下使用。如果在多線程下,一個線程進入了if (singleton == null)判斷語句塊,還未來得及往下執行,另一個線程也通過了這個判斷語句,這時便會產生多個實例。所以在多線程環境下不可使用這種方式。

  (4)懶漢式(線程安全,同步方法)[不推薦用]

public class Singleton {
  private static Singleton singleton;
  private Singleton() {}
  public static synchronized Singleton getInstance() {
    if (singleton == null) {
      singleton = new Singleton();
    }
    return singleton;
  }
} 優點:解決上面第三種實現方式的線程不安全問題,做個線程同步就可以了,于是就對getInstance()方法進行了線程同步。 缺點:效率太低了,每個線程在想獲得類的實例時候,執行getInstance()方法都要進行同步。而其實這個方法只執行一次實例化代碼就夠了,后面的想獲得該類實例,直接return就行了。方法進行同步效率太低要改進。

  (5)懶漢式(線程安全,同步代碼塊)[不可用]

public class Singleton {
  private static Singleton singleton;
  private Singleton() {}
  public static Singleton getInstance() {
    if (singleton == null) {
      synchronized (Singleton.class) {
        singleton = new Singleton();
      }
    }
    return singleton;
  }
} 由于第四種實現方式同步效率太低,所以摒棄同步方法,改為同步產生實例化的的代碼塊。但是這種同步并不能起到線程同步的作用。跟第3種實現方式遇到的情形一致,假如一個線程進入了if (singleton == null)判斷語句塊,還未來得及往下執行,另一個線程也通過了這個判斷語句,這時便會產生多個實例。

  (6)雙重檢查[推薦用]

public class Singleton {
  private static volatile Singleton singleton;
  private Singleton() {}
  public static Singleton getInstance() {
    if (singleton == null) {
      synchronized (Singleton.class) {
        if (singleton == null) {
          singleton = new Singleton();
        }
      }
    }
    return singleton;
  }
} Double-Check概念對于多線程開發者來說不會陌生,如代碼中所示,我們進行了兩次if (singleton == null)檢查,這樣就可以保證線程安全了。這樣,實例化代碼只用執行一次,后面再次訪問時,判斷if (singleton == null),直接return實例化對象。 優點:線程安全;延遲加載;效率較高。

  (7).靜態內部類[推薦用]

public class Singleton {
  private Singleton() {}
  private static class SingletonInstance {
    private static final Singleton INSTANCE = new Singleton();
  }
  public static Singleton getInstance() {
    return SingletonInstance.INSTANCE;
  }
} 這種方式跟餓漢式方式采用的機制類似,但又有不同。兩者都是采用了類裝載的機制來保證初始化實例時只有一個線程。不同的地方在餓漢式方式是只要Singleton類被裝載就會實例化,沒有Lazy-Loading的作用,而靜態內部類方式在Singleton類被裝載時并不會立即實例化,而是在需要實例化時,調用getInstance方法,才會裝載SingletonInstance類,從而完成Singleton的實例化。 類的靜態屬性只會在第一次加載類的時候初始化,所以在這里,JVM幫助我們保證了線程的安全性,在類進行初始化時,別的線程是無法進入的。 優點:避免了線程不安全,延遲加載,效率高。

  (8).枚舉[推薦用]

public enum Singleton {
  INSTANCE;
  public void whateverMethod() { }
} 借助JDK1.5中添加的枚舉來實現單例模式。不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象。可能是因為枚舉在JDK1.5中才添加,所以在實際項目開發中,很少見人這么寫過。

5.優缺點:

(1)單例模式的優點:

[1]在內存中只有一個對象,節省內存空間。 [2]避免頻繁的創建銷毀對象,可以提高性能。 [3]避免對共享資源的多重占用。 [4]可以全局訪問。 [5]靈活性:因為類控制了實例化過程,所以類可以靈活更改實例化過程。 [6]實例控制:會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例。

(2)單例模式的缺點:

[1]開銷:雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。 [2]可能的開發混淆:使用單例對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用new關鍵字實例化對象。因為可能無法訪問庫源代碼,因此應用程序開發人員可能會意外發現自己無法直接實例化此類。 [3]對象生存期:不能解決刪除單個對象的問題。

6.注意事項

(1)只能使用單例類提供的方法得到單例對象,不要使用反射,否則將會實例化一個新對象。 (2)不要做斷開單例類對象與類中靜態引用的危險操作。 (3)多線程使用單例使用共享資源時,注意線程安全問題。

7.相關問題

(1)單例模式的對象長時間不用會被jvm垃圾收集器收集嗎

除非人為地斷開單例中靜態引用到單例對象的聯接,否則jvm垃圾收集器是不會回收單例對象的。

(2)在一個jvm中會出現多個單例嗎

在分布式系統、多個類加載器、以及序列化的的情況下,會產生多個單例,這一點是無庸置疑的。那么在同一個jvm中,會不會產生單例呢?使用單例提供的getInstance()方法只能得到同一個單例,除非是使用反射方式,將會得到新的單例。代碼如下 Class c = Class.forName(Singleton.class.getName()); Constructor ct = c.getDeclaredConstructor(); ct.setAccessible(true); Singleton singleton = (Singleton)ct.newInstance(); 這樣,每次運行都會產生新的單例對象。所以運用單例模式時,一定注意不要使用反射產生新的單例對象。

?(3)懶漢式單例線程安全嗎

主要是網上的一些說法,懶漢式的單例模式是線程不安全的,即使是在實例化對象的方法上加synchronized關鍵字,也依然是危險的,但是筆者經過編碼測試,發現加synchronized關鍵字修飾后,雖然對性能有部分影響,但是卻是線程安全的,并不會產生實例化多個對象的情況。

?  (4)單例模式只有餓漢式和懶漢式兩種嗎

餓漢式單例和懶漢式單例只是兩種比較主流和常用的單例模式方法,從理論上講,任何可以實現一個類只有一個實例的設計模式,都可以稱為單例模式。

(5)單例類可以被繼承嗎

餓漢式單例和懶漢式單例由于構造方法是private的,所以他們都是不可繼承的,但是其他很多單例模式是可以繼承的,例如登記式單例。

(6)餓漢式單例好還是懶漢式單例好

在java中,餓漢式單例要優于懶漢式單例。C++中則一般使用懶漢式單例。

轉載于:https://www.cnblogs.com/yysbolg/p/7380568.html

總結

以上是生活随笔為你收集整理的设计模式(2)--Singleton(单例模式)--创建型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。