像是登錄(registry)物件、偏好設定物件等等
這些系統資訊的物件,常被其它的物件實體化取得資訊
在每個物件要取得資訊的時後都要先new一次才能用get()方法取得資訊
如果這個物件在很多處都有用到的話
那就會被實體化(new)很多次,可能會有很多問題產生
如:程式行為異常、資源使用過量或是不一致的問題
那要如何避免這樣問題呢?
工程師之間約定好只能實體化一次 : 這不用說問題有多大了XD
全域變數 : 在一開頭就要先建立好物件,不論是否會用到這個物件,這樣會造成資源的浪費
獨體化 : 可以在有使用到的時後才建立物件,有效的利用資源避免浪費
獨體化是利用靜態類別變數、靜態方法以及一些存取的修飾,來達到保証物件只被實體化一次
獨體設計根據不同問題的適用性有三種設計方法
- 同步化getInstance()
public class Singleton { private static Singleton uniqueInstance; private Singleton(){} public static synchronized Singleton getInstance(){ if (uniqueInstance == null){ uniqueInstance = new Singleton(); } return uniqueInstance; } }
synchronized 關鍵字的作用就是同步化
會確認所有呼叫getInstance()都結束後才會繼續執行接下來的程式
這可以避免A物件正在建立Singleton的空窗期中,有其它物件正在檢查Singleton是否被建立
造成不一致的問題
但如果很頻繁會呼叫getInstance(),每次都要等待後才會處理
選用這個方法這樣會降低效率
- 率先實體化(Eagerly instants)
public class Singleton { private static Singleton uniqueInstance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return uniqueInstance; } }
在一開始進入Singleton類別的時後就先實體化類別,無論是否真的有使用到
如果確定一定要有一個Singleton類別,用這個方法也不錯。
- 雙重檢查上鎖(Double-checked locking)
public class Singleton { private volatile static Singleton uniqueInstance; private Singleton(){} public static Singleton getInstance(){ if (uniqueInstance == null){ synchronized (Singleton.class) { if (uniqueInstance == null){ uniqueInstance = new Singleton(); } } } return uniqueInstance; } }
如果沒有效能上的考量就不需要用這個方法,不然有種殺雞用牛刀的感覺
用這個方法要注意要用JAVA 2的版本是5以上唷