Design Pattern: Singleton 模式
一句話概括:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
Singleton的英文意義是獨身,也就是只有一個人,應(yīng)用在物件導(dǎo)向語言上,通常翻譯作單例:單一個實例(Instance)。?
很多時候,您會需要Singleton模式,例如印表機管理,您希望程式中只能有一個Print Spooler,以避免兩個列印動作同時輸入至印表機中;例如資料庫管理,因為建立連接(Connection)物件會耗用資源,您希望程式中只能有一個 連接物件,所有其它的程式都透過這個物件來連接資料庫,以避免連接物件的重復(fù)開啟造成資源的耗用;例如系統(tǒng)程式屬性檔的讀取,您使用單一個物件來讀取屬性 內(nèi)容,而程式的其它部份都向這個物件要求屬性資料,而不是自行讀取屬性資料。?
以印表機設(shè)計為例,有的設(shè)計人員會采取全域變數(shù)的方式來建立實例,并在程式中隨機取用這個實例,Java雖然不支援全域變數(shù),但透過將物件包裝在一個類別之中,也有人會采用這樣的寫法:
無論全域變數(shù)或是以上的例子,都無法保證只產(chǎn)生唯一個實例,您也許會注意不犯這個錯誤,但與您共同工作的伙伴也許會直覺的使用建構(gòu)方法來產(chǎn)生一個 PrintSpooler實例。?
Singleton模式可以保證一個類別只有一個實例,并提供一個訪問(visit)這個實例的方法。?
一個Singleton實作即為Java中的java.lang.Runtime類別,每個Java程式執(zhí)行時都有一個唯一的Runtime物件,可以透過它提供的靜態(tài)方法getRuntime()方法來取得這個物件,例如:
Runtime runtime = Runtime.getRuntime();
取得Runtime物件之后,您可以透過它進行一些外部命令的執(zhí)行、進行垃圾處理等等指令,您可以開啟Runtime.java類別,開頭的幾行是這樣寫的:
public class Runtime { private static Runtime currentRuntime = new Runtime(); public static Runtime getRuntime() { return currentRuntime; } /** Don't let anyone else instantiate this class */ private Runtime() {} // 以下略 }有幾個實作上面結(jié)構(gòu)的方法,可以在第一次需要實例時再建立物件,也就是采用所謂的Lazy Initialization:
public class Singleton { private static Singleton instance = null; private Singleton() { // .... } public static Singleton getInstance() { if (instance == null) {instance = new Singleton(); }return instance; } // .. 其它實作 }上面的實作適用于單執(zhí)行緒的程式,在多執(zhí)行緒的程式下,以下的寫法在多個執(zhí)行緒的競爭資源下,將仍有可能產(chǎn)生兩個以上的實例,例如下面的情況:
Thread1: if(instance == null) // true?
Thread2: if(instance == null) // true?
Thread1: instance = new Singleton(); // 產(chǎn)生一個實例?
Thread2: instance = new Singleton(); // 又產(chǎn)生一個實例?
Thread1: return instance; // 回傳一個實例?
Thread2: return instance; // 又回傳一個實例
在多執(zhí)行緒的環(huán)境下,為了避免資源同時競爭而導(dǎo)致如上產(chǎn)生多個實例的情況,加上同步(synchronized)機制
public class Singleton {private static Singleton instance = null;private Singleton(){}synchronized static public Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;} }不過這種簡單的寫法不適合用于像伺服器這種服務(wù)很多執(zhí)行緒的程式上,同步機制會造成相當(dāng)?shù)男艿吐?#xff0c;為了顧及Singleton、Lazy Initialization與效能問題,因而有了Double-check Locking的模式:
public class Singleton {private static Singleton instance = null;private Singleton(){}public static Singleton getInstance() {if (instance == null){synchronized(Singleton.class){if(instance == null) {instance = new Singleton();}}}return instance;} }Java中Runtime類別的作法就簡單多了,它舍棄了Lazy Initialization,如果您的實例初始化不是很久的話,可以用這種方式:
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { // .... } public static Singleton getInstance() { return instance; } // 其它實作 }Singleton本身的觀念簡單但應(yīng)用很廣,因而很多時候必須對實際環(huán)境作一些考量與調(diào)整,建議您也看看有關(guān)于Singleton的這篇?討論。
總結(jié)
以上是生活随笔為你收集整理的Design Pattern: Singleton 模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IT行业: 嵌入式工程师的进阶之路
- 下一篇: 异常处理汇总-开发工具