1. 模式介紹
模式的定義
確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例。
模式的使用場景
確保某個類有且只有一個對象的場景,例如創建一個對象需要消耗的資源過多,如要訪問 IO 和數據庫等資源。
2. UML類圖
角色介紹:
(1)Client : 高層客戶端。
(2)Singleton : 單例類。
3. 模式的簡單實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
public class Singleton { private static Singleton intance; private Singleton() {} public static Singleton getInstance() { /* * 一開始多線程進來,遇到鎖,一個線程進去,是為空,new對象; 后續線程進入,不為空,不操作;最后直接返回 * 對象不為空,再有多個線程進入該函數,不為空,不執行加鎖操作,直接返回 */ if (intance == null ) { synchronized (Singleton. class ) { if (intance == null ) { intance = new Singleton(); } } } return intance; } } class Singleton1 { // 懶漢式 private static Singleton1 intance = new Singleton1(); //懶的,程序運行的時候就加載出來了 private Singleton1() {} public static Singleton1 getInstance() { return intance; } } class Singleton2 { // 餓漢式 private static Singleton2 intance; private Singleton2() {} public static Singleton2 getInstance() { //用到的時候 才加載 if (intance == null ) { intance = new Singleton2(); } return intance; } } class Singleton3 { // 餓漢式 線程安全 private static Singleton3 intance; private Singleton3() {} public synchronized static Singleton3 getInstance() { //用到的時候 才加載, 加鎖 多線程調用,都有一個加鎖的動作 if (intance == null ) { intance = new Singleton3(); } return intance; } } class Singleton4 { // 餓漢式 線程安全 private static Singleton4 intance; private Singleton4() {} public static Singleton4 getInstance() { //用到的時候 才加載 synchronized (Singleton4. class ) { // 加鎖 效率跟3差不多 if (intance == null ) { intance = new Singleton4(); } } return intance; } } |
4.優點與缺點
(1)優點:
A.由于單例模式在內存中只有一個實例,減少了內存開支,特別是一個對象需要頻繁地創建、銷毀時,而且創建或銷毀時性能又無法優化,單例模式的優勢就非常明顯。
B.由于單例模式只生成一個實例,所以減少了系統的性能開銷,當一個對象的產生需要比較多的資源時,如讀取配置、產生其他依賴對象時,則可以通過在應用啟動時直接產生一個單例對象,然后用永久駐留內存的方式來解決;
C.單例模式可以避免對資源的多重占用,例如一個寫文件動作,由于只有一個實例存在內存中,避免對同一個資源文件的同時寫操作。
D.單例模式可以在系統設置全局的訪問點,優化和共享資源訪問,例如可以設計一個單例類,負責所有數據表的映射處理。
(2)缺點
A.單例模式一般沒有接口,擴展很困難,若要擴展,除了修改代碼基本上沒有第二種途徑可以實現。