Java 單例模式詳解

概念:
  java中單例模式是一種常見的設計模式,單例模式分三種:懶漢式單例、餓漢式單例、登記式單例三種。
  單例模式有一下特點:
  1、單例類只能有一個實例。
  2、單例類必須自己創建自己的唯一實例。
  3、單例類必須給所有其他對象提供這一實例。
  單例模式確保某個類只有一個實例,而且自行實例化並向整個系統提供這個實例。在計算機系統中,線程池、緩存、日誌對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。這些應用都或多或少具有資源管理器的功能。每臺計算機可以有若干個打印機,但只能有一個Printer Spooler,以避免兩個打印作業同時輸出到打印機中。每臺計算機可以有若干通信端口,系統應當集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調用。總之,選擇單例模式就是爲了避免不一致狀態,避免政出多頭。


首先看一個經典的單例實現。

public class Singleton {

    private static Singleton uniqueInstance = null;

 

    private Singleton() {

       // Exists only to defeat instantiation.

    }

 

    public static Singleton getInstance() {

       if (uniqueInstance == null) {

           uniqueInstance = new Singleton();

       }

       return uniqueInstance;

    }

    // Other methods...

}

Singleton通過將構造方法限定爲private避免了類在外部被實例化,在同一個虛擬機範圍內,Singleton的唯一實例只能通過getInstance()方法訪問。(事實上,通過Java反射機制是能夠實例化構造方法爲private的類的,那基本上會使所有的Java單例實現失效。此問題在此處不做討論,姑且掩耳盜鈴地認爲反射機制不存在。)

但是以上實現沒有考慮線程安全問題。所謂線程安全是指:如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。或者說:一個類或者程序所提供的接口對於線程來說是原子操作或者多個線程之間的切換不會導致該接口的執行結果存在二義性,也就是說我們不用考慮同步的問題。顯然以上實現並不滿足線程安全的要求,在併發環境下很可能出現多個Singleton實例。

複製代碼

   TestStream {
      String name;
      String getName() {
          name;
     }
       setName(String name) {
         .name = name;
     } 
           TestStream(){}           
       TestStream ts1=;
            TestStream getTest(){
         (ts1==){
             ts1= TestStream();
         }
          ts1;
     }
       getInfo(){
         System.out.println("output message "+name);
     }
 }

複製代碼

複製代碼

   TestMain {
        main(String [] args){
         TestStream s=TestStream.getTest();
         s.setName("張孝祥");
         System.out.println(s.getName());
         TestStream s1=TestStream.getTest();
         s1.setName("非張孝祥");
         System.out.println(s1.getName());
         s.getInfo();
         s1.getInfo();
         (s==s1){
             System.out.println("創建的是同一個實例");
         } (s!=s1){
             System.out.println("創建的不是同一個實例");
         }{
             System.out.println("application error");
         }
     }
 }

複製代碼

運行結果:
  張孝祥
  非張孝祥
  output message 非張孝祥
  output message 非張孝祥
  創建的是同一個實例

結論:由結果可以得知單例模式爲一個面向對象的應用程序提供了對象惟一的訪問點,不管它實現何種功能,整個應用程序都會同享一個實例對象

1.餓漢式單例類

複製代碼

    Singleton1 {
           Singleton1() {}
             Singleton1 single =  Singleton1();
            Singleton1 getInstance() {
          single;
     }
 }

複製代碼

2.懶漢式單例類

複製代碼

    Singleton2 {
           Singleton2() {}
            Singleton2 single=;
              Singleton2 getInstance() {
           (single == ) {  
              single =  Singleton2();
          }  
          single;
     }
 }

複製代碼

3.登記式單例類

複製代碼

  java.util.HashMap;
  java.util.Map;
     Singleton3 {
       Map<String,Singleton3> map =  HashMap<String,Singleton3>();
     {
         Singleton3 single =  Singleton3();
         map.put(single.getClass().getName(), single);
     }
           Singleton3(){}
            Singleton3 getInstance(String name) {
         (name == ) {
             name = Singleton3..getName();
             System.out.println("name == null"+"--->name="+name);
         }
         (map.get(name) == ) {
              {
                 map.put(name, (Singleton3) Class.forName(name).newInstance());
             }  (InstantiationException e) {
                 e.printStackTrace();
             }  (IllegalAccessException e) {
                 e.printStackTrace();
             }  (ClassNotFoundException e) {
                 e.printStackTrace();
             }
         }
          map.get(name);
     }
           String about() {    
          "Hello, I am RegSingleton.";    
     }    
        main(String[] args) {
         Singleton3 single3 = Singleton3.getInstance();
         System.out.println(single3.about());
     }
 }

複製代碼

轉載:http://www.cnblogs.com/whgw/archive/2011/10/05/2199535.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章