經典的單件模式
public class Singleton {
private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體,
// 其他有用的實體變數寫在這里
//構造器宣告為私有,只有Singleton可以實體化這個類!
private Singleton() ()
public static Singleton getInstance(){
if(uniqueInstance == null){
uniqueInstance = new Singleton();//getInstance()方法提供了一種實體化該類的方式,也回傳它的一個實體,
}
return uniqueInstance ;
}
}
單件模式沒有公開的構造器,構造器宣告為私有;為了獲得一個單件物件,不是實體化一個,只是請求一個實體,因此類有一個靜態方法,稱為getInstance(),
用途:常常被用來管理資源池,像連接或者執行緒池,
你有一個包含注冊表設定的物件,你不想讓這個物件有多個副本,到處賦值一這會導致混亂,通過使用像單件模式這樣的物件,你可以確保應用中的每個物件使用同一全域資源,
例子--巧克力工廠
一個Choc-O-Hoic公司的工業強度巧克力鍋爐控制器類
public class ChocolateBoiler {
private boolean empty;
private boolean boiled;
//這段代碼只有在鍋爐空的時候才啟動!
public ChocolateBoiler(){
empty = true;
boiled = false;
}
//要往鍋爐里填充原料,鍋爐必須是空的,一旦鍋爐滿了,我們就設定empty和boiled標志
public void fill() {
if(isEmpty()) {
empty = false;
boiled = false;
//往鍋爐里填充牛奶/巧克力混合物
}
}
//要排空鍋爐,鍋爐必須是滿的 (非空) 且煮過的,一旦排出完畢,我們把empty設定回true,
public void drain() {
if(!isEmpty() && isBoiled()) {
//排出煮沸的牛奶和巧克力
empty = true;
}
}
//要煮混合物,鍋爐必須是滿而且未煮過的,一旦煮沸,我們r把boiled標志設為true,
public void boil() {
if(!isEmpty() &&!isBoiled()) {
//將爐內物煮沸
boiled = true;
}
}
public boolean isEmpty() {return empty;}
public boolean isBoiled() (return boiled;}
}
改成單件模式
public class ChocolateBoiler {
private boolean empty;
private boolean boiled;
//改動一:
private static Chocolateboiler uniqueinatance;
//改動二:
private ChocolateBoiler(){
empty = true;
boiled = false;
}
//改動三:
public static ChocolateBoiler getInstance(){
if(uniqueInstance == null) {
uniqueInstance = new ChocolateBoiler()
}
return uniqueInstance;
}
public void fill() {
if(isEmpty()) {
empty = false;
boiled = false;
//往鍋爐里填充牛奶/巧克力混合物
}
}
// 剩下的chocolateBoiler代碼·
}
單件模式
單件模式:確保一個類只有一個實體,并提供一個全域訪問點;
類圖:
添加執行緒造成的問題
解決多執行緒:通過把getInstance()方法變成同步(Synchronized)方法;
但是同步導致性能開銷大
改進多執行緒
1.如果getlnstance()的性能對應用來說不是很關鍵,什么也不做,
2.轉為急切(eagerly) 創建實體,而不用延遲創建
用這個方法,當類被加載時,我們依靠JVM來創建單件的唯一實體,JVM 保證在任何執行緒訪問靜態uniqueInstance變數之前,實體會被創建,
public class Singleton {
//在靜態初始化器中創建單件實體,這段代碼保證是執行緒安全的!
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;//我們已經有了一個實體,因此回傳它即可,
}
}
3.用“雙重檢查加鎖”在getlnstance()減少使用同步
雙重檢查加鎖不適用1.4以及更早版本的Java!
public class Singleton {
//volatile關鍵詞確保:當uniquelnstance變數被初始化為單件實體時,多個執行緒正確處理uniquelnstance變數
private volatilestatic Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if(uniqueInstance == null) {//檢查實體,如果沒有,進入同步區塊,
synchronized(Singleton.class){//注意,只有第一次才同步
if(uniqueInstance == null) {
uniqueInstance = new Singleton();//進入區塊后,再檢查一次,如果依然是空的,創建一個實體,
}
}
}
return uniqueInstance;
}
}
總結
單件,確保一個類只有一個實體,并提供全域訪問點,
當你需要確保應用中的某個類只有一個實體,就用單件模式吧,
要點
1.單件模式確保應用中個類最多只有一個實體,
2.單件模式也提供訪問此實體的全域點,
3.Java的單件實作用了一個私有構造器、一個靜態方法以及一個靜態變數,
4.檢查你的性能和資源約束,為多執行緒應用小心選擇一個適當的單件實作 (我們應該把所有應用都考慮為是多執行緒的),
5.提防雙重檢查加鎖實作,Java 5之前的版本,不是執行緒安全的
6.如果你使用多個類加載器,要小心,可能導致單件實作失效,導致出現多個實體,
7.你可以使用Java的列舉來簡化單件的實作,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/550474.html
標籤:其他