(Singleton)單例模式的Java實現

原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://haolloyin.blog.51cto.com/1177454/332469            

               

   

單例模式(Singleton):當系統中只需要的某個類的唯一對象時,可以使用該模式。

爲什麼會用到該模式?因爲有時候某些對象的創建需要耗費大量的資源、使用單一(唯一)的對象實例來維護某些共享數據等,在這些場景下即可採用單例模式進行設計,可以適當地漸少內存開銷,因爲此時該唯一對象不會(被限制了)頻繁地創建。

一個簡單單例類圖如下:

代碼實現如下:

單例類Singleton01

 

class Singleton01 {
  private static Singleton01 singleton = null;
  // 私有的構造函數,限制外部環境的非法創建和訪問
  private Singleton01() {
    //一些初始化操作
  }
  // 靜態方法,用於創建單例類的“唯一”實例
  public static Singleton01 getInstance() {
    if (singleton == null) {
      singleton = new Singleton01();
    }
    return singleton;
  }
  // 單例類也需要提供其他靜態方法給外部環境訪問,完成一定的服務
  public void doSomethings() {
    System.out.println("do somethings ...");
  }
}

客戶端類Client

public class Client {
  public static void main(String[] args) {
    Singleton01 s1 = Singleton01.getInstance();
    Singleton01 s2 = Singleton01.getInstance();
    Singleton01 s3 = Singleton01.getInstance();

    System.out.println("s1 == s2 : " + (s1 == s2));
    System.out.println("s1 == s3 : " + (s1 == s3));
    System.out.println("s2 == s3 : " + (s2 == s3));
  }
}

注意:如此設計的單例類並不是線程安全的,原因大家都明白,在getInstance()方法中的條件判斷並不是原子性的,當多個線程同時訪問時則可能出現混亂,所以我們可以在該方法前加上synchronized關鍵字來保證其被同步訪問。但是,學過OS進程同步知識的我們知道,此時的同步還不是很嚴格的,我記得是需要兩個條件判斷來實現的,具體的優化實現請參考具體的教材。

其實,如果真正地只想某個類僅僅擁有一個唯一的實例,使用下面這種“餓漢式”的實現更加合理些,請詳看其中的不同之處

“餓漢式”Singleton02類:

class Singleton02 {
  // 直接爲該單例類創建一個實例對象
  private final static Singleton02 singleton = new Singleton02();
  private Singleton02() {
    //一些初始化操作
  }
  // 直接返回唯一的單例對象
  public static Singleton02 getInstance() {
    return singleton;
  }
  public void doSomethings() {
    System.out.println("do somethings ...");
  }
}

另外,有時我們並不僅僅滿足於一個唯一的實例對象,而是需要爲數不多但是又不能超過一定數量的實例對象,此時可以用一個容器來預先創建並裝載一定數量的實例,在提供一個外部接口供外部訪問獲得其中一個實例。

此時的類圖如下:

代碼實現如下:

Singleton03類:

 

class Singleton03 {
  private final static int MAX_NUM_OF_INSTANCE = 3;
  private static List<Singleton03> singletonList = new ArrayList<Singleton03>();
    //以靜態代碼塊的方式來初始化一定數量的單例對象
  static {
    for(int i = 0; i < MAX_NUM_OF_INSTANCE; i++) {
      singletonList.add(new Singleton03());
    }
  }
    public static Singleton03 getInstance() {
    //從單例類已持有的實例中隨機取出一個實例
    Random random = new Random();
    int id = random.nextInt(MAX_NUM_OF_INSTANCE);
    return singletonList.get(id);
  }
    private Singleton03() {
    //一些初始化操作
  }
    public void doSomethings() {
    System.out.println("do somethings ...");    
  }
}

以上是我學習參考了秦小波的《設計模式之禪》中的單例模式以及其他之前看過的相關書籍之後,結合自己的理解和總結得出的,希望以此來鞏固學過的知識,更希望能與正在學習中的大家互相學習共同進步!

 

本文出自 “螞蟻” 博客,請務必保留此出處http://haolloyin.blog.51cto.com/1177454/332469

   


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