基本概念 ingleton 是一種創建性模型
它用來確保只產生一個實例
並提供一個訪問它的全局訪問點
對一些類來說
保證只有一個實例是很重要的
比如有的時候
數據庫連接或 Socket 連接要受到一定的限制
必須保持同一時間只能有一個連接的存在
再舉個例子
集合中的 set 中不能包含重復的元素
添加到set裡的對象必須是唯一的
如果重復的值添加到 set
它只接受一個實例
JDK中正式運用了Singleton模式來實現 set 的這一特性
大家可以查看java
util
Collections裡的內部靜態類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
= Singleton
getInstance();
Singleton s
= Singleton
getInstance();
if (s
==s
)
System
out
println
(
s
is the same instance with s
);
else
System
out
println
(
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
incetance
this should always work
System
out
println
(
Creating one instance
);
try {
s
= new Singleton();
} catch (SingletonException e)
{
System
out
println(e
getMessage());
}
// try to create another
spooler
should fail
System
out
println
(
Creating two instance
);
try {
s
= new Singleton();
} catch (SingletonException e)
{
System
out
println(e
getMessage());
}
}
}
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 實例
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27471.html