熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

在Java中應用設計模式Singleton

2013-11-23 19:45:17  來源: Java高級技術 

          基本概念

  Singleton 是一種創建性模型它用來確保只產生一個實例並提供一個訪問它的全局訪問點對一些類來說保證只有一個實例是很重要的比如有的時候數據庫連接或 Socket 連接要受到一定的限制必須保持同一時間只能有一個連接的存在再舉個例子集合中的 set 中不能包含重復的元素添加到set裡的對象必須是唯一的如果重復的值添加到 set它只接受一個實例JDK中正式運用了Singleton模式來實現 set 的這一特性大家可以查看javautilCollections裡的內部靜態類SingletonSet的原代碼其實Singleton是最簡單但也是應用最廣泛的模式之一在 JDK 中隨處可見

  簡單分析

  為了實現 Singleton 模式我們需要的是一個靜態的變量能夠在不創建對象的情況下記憶是否已經產生過實例了靜態變量或靜態方法都可以在不產生具體實例的情況下直接調用這樣的變量或方法不會因為類的實例化而有所改變在圖的結構中可以看到uniqueInstance 就是這個獨立的靜態變量它可以記憶對象是否已經實例化了在靜態方法 Instance 中對這個變量進行判斷若沒有實例化過就產生一個新的對象如果已經實例化了則不再產生新的對象仍然返回以前產生的實例

  : Singleton 模式結構

  

    具體實施

  實現 Singleton 模式的辦法通常有三種

  一 用靜態方法實現 Singleton 這種方法是使用靜態方法來監視實例的創建為了防止創建一個以上的實例我們最好把構造器聲明為 private

  這樣可以防止客戶程序員通過除由我們提供的方法之外的任意方式來創建一個實例如果不把構造器聲明為private編譯器就會自作聰明的自動同步一個默認的friendly構造器這種實現方法是最常見的也就是圖中結構的標准實現



public class Singleton {

  private static Singleton s;

  private Singleton(){};

  /**

  * Class method to access the singleton instance of the class

  */

  public static Singleton getInstance() {

  if (s == null)

  s = new Singleton();

  return s;

  }

  }

  // 測試類

  class singletonTest {

  public static void main(String[] args) {

  Singleton s = SingletongetInstance();

  Singleton s = SingletongetInstance();

  if (s==s)

  Systemoutprintln(s is the same instance with s);

  else

  Systemoutprintln(s is not the same instance with s);

  }

  }

  singletonTest運行結果是:

  s is the same instance with s

  這證明我們只創建了一個實例

  二 以靜態變量為標志實現 Singleton 在類中嵌入一個靜態變量做為標志每次都在進入構造器的時候進行檢查

  問題在於構造器沒有返回類型如果確定創建一個實例成功與否一個方法是調用一個函數來檢查創建是否成功然後簡單的返回一個來自靜態變量的值但是這樣做是不優雅的而且容易發生錯誤比較好的做法是創建一個當創建了一個以上的實例時可以拋出異常的類這個類僅僅是調用父類方法好處是用了自己命名的異常類型錯誤信息更加清晰:



class SingletonException extends RuntimeException {

  public SingletonException(String s) {

  super(s);

  }

  }

  class Singleton {

  static boolean instance_flag = false; // true if instance

  public Singleton() {

  if (instance_flag)

  throw new SingletonException(Only one instance allowed);

  else

  instance_flag = true; // set flag for instance

  }

  }

  // 測試類

  public class singletonTest {

  static public void main(String argv[]) {

  Singleton s s;

  // create one incetancethis should always work

  Systemoutprintln(Creating one instance);

  try {

  s = new Singleton();

  } catch (SingletonException e) {

  Systemoutprintln(egetMessage());

  }

  // try to create another spooler should fail

  Systemoutprintln(Creating two instance);

  try {

  s = new Singleton();

  } catch (SingletonException e) {

  Systemoutprintln(egetMessage());

  }

  }

  }

  singletonTest運行結果是:

  Creating one instance

  Creating two instance

  Only one instance allowed

  可以看出第一個實例順利創建第二個實例創建實拋出了我們自定義的異常

  三 用注冊器機制來創建 Singleton 首先用集合中的Hashtable 和Enumeration來實現addItem(Object key Object value)getItem(Object key) removeItem(Object key)等方法實現一個管理器將key和value一一關聯起來客戶程序員創建實例前首先用addItem方法進行注冊再用getItem方法獲取實例Hashtable中的key是唯一的從而保證創建的實例是唯一的具體實現限於篇幅不再細說在Prototype模型的應用一文中我將會給出一個實現注冊器的代碼用注冊器機制來創建 Singleton模式的好處是易於管理可以同時控制多個不同類型的Singleton 實例

  小結

  Singleton模式可以方便的進行擴充產生指定數目的實例

  在The Design Patterns Java Companion 一書中曾提到過用靜態類的方式來實現 Singleton模式並指出javalangMath就是一個例子這裡我並不表示贊同因為Math並不是一個真正的對象我們只是直接調用Math類所包裝的靜態方法而已根本就沒有創建實例的過程又從何說起只產生一個實例呢?這個問題我曾到Javaranch的論壇上發過帖子所有回帖的人也都是對這一觀點持否定態度

  在多線程的程序中singleton可能會變的不可靠可能會出現多個實例解決的辦法很簡單加個同步修飾符: public static synchronized Singleton getInstance() 這樣就保證了線程的安全性

  最後要說的是大家可能會看見一些其他實現Singleton模式的方法因為模式在具體的應用時是靈活的不是一成不變的並沒有一個固定的做法但大都是上面幾種方法的變形


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27404.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.