模擬排球比賽
阿新 • • 發佈:2020-11-22
單例模式
GoF定義:保證一個類只有一個物件,並且提供一個全域性的訪問點
概念
一個特別的類只有一個例項,無論什麼時候使用都是這同一個例項
例子
現實生活:假設有兩個板球隊伍在比賽,賽前兩隊的隊長要投幣決定哪方先擊球,此時每個隊的隊長只能有一個,如果原來沒有,那麼要新選出一個隊長
程式碼世界:程式碼只在一個檔案系統上操作,那麼這個檔案系統的物件應該是全域性唯一的
展示
- 將構造器宣告為private
- 當建立這個類的例項時,如果已經存在,則使用這個例項,否則新建一個例項
public class SingletonPattern { public static void main(String[] args) { System.out.println("***Singleton Pattern Demo***\n"); System.out.println("Trying to make a captain for our team"); MakeACaptain c1 = MakeACaptain.getCaptain(); System.out.println("Trying to make another captain for our team"); MakeACaptain c2 = MakeACaptain.getCaptain(); if (c1 == c2) { System.out.println("c1 and c2 are same instance"); } } } class MakeACaptain { private static MakeACaptain makeACaptain; private MakeACaptain() {} public static MakeACaptain getCaptain() { if (makeACaptain == null) { makeACaptain = new MakeACaptain(); System.out.println("New Captain selected for our team"); } else { System.out.print("You already have a Captain for your team."); System.out.println("Send him for the toss."); } return makeACaptain; } }
附加資訊
上面程式碼的初始化模式為lazy initialization
。因為直到靜態方法被呼叫這個物件都不存在(可以在靜態變數預設值直接新建一個物件)
上面程式碼的例項建立方式是執行緒不安全的,即(判斷物件是否為空可能會讓兩個執行緒進入,那麼會建立兩個物件,那麼它們持有的就不是同一個物件)
改進方式:
- 將返回例項的方法設為
synchronized
(同步操作會有額外開銷(鎖的開銷))
public static synchronized MakeACaptain getCaptain()
- 提前把例項建立好
class MakeACaptain { private static MakeACaptain makeACaptain = new MakeACaptain(); private MakeACaptain() {} public static synchronized MakeACaptain getCaptain() { return makeACaptain } }
- 不使用同步,也不使用提前初始化,Java中標準的單例實現(這個方法的牛逼之處在於,類在載入時會有靜態變數初始化的過程,這種方法利用了內部類的靜態成員變數初始化需要載入內部類,實現了
lazy initialization
。對於final變數,只有當構造器呼叫完成,其它的執行緒才能看到,這個(Java語言的)機制保證了執行緒安全)
class MakeACaptain { private static MakeACaptain _captain; private MakeACaptain() { } //Bill Pugh solution private static class SingletonHelper{ //Nested class is referenced after getCaptain() is called private static final MakeACaptain _captain = new MakeACaptain(); } public static MakeACaptain getCaptain() { return SingletonHelper._captain; } }