顧名思義,單例模式的特點就是保證一個類僅有一個實例。因爲這個模式只和一個類有關,沒有類與類之間的關係,所有就不給出圖示了。那麼還是先說一下基本的定義。
單例模式(Singleton),保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
通常我們可以讓一個全局變量使得一個對象被訪問,但它不能防止你實例化多個對象。一個最好的辦法就是,讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例可以被創建,並且它可以提供一個訪問該實例的方法。平時,我們常用單例模式的地方通常是多線程。
因爲Objective C傳承了Smalltalk語言,所以在Objective C中實現單例模式和C++和C#以及Java都不太一樣。因爲要保證類型對象的單一性,所以就要考慮Objective C在實例化對象時候的各種方式。因爲在Objective C中創建的各個類型都繼承自NSObject類型,所以我們需要考慮NSObject類型裏實例化的方法,下面讓我們展開來說。
在Objective C的實例化對象的方式主要有三種,分別如下:
-
obj = [NSObject new];
-
obj = [[NSObject alloc]init];
-
obj = [[NSObject allocWithZone]init];
NSObject類參考文檔裏記錄第三種方法是因爲歷史原因遺留下來的,在當前的Objective
C中已經不再使用,所以我們就不考慮這種方式了。下面讓我們主要看一下前兩種方式。
第一種方式,用new方法初始化其實是第二種方式的總和,當調用new方法時,其實是先調用了alloc方法進行isa(is a pointer)操作,創建指針,指向內存中的數據結構,緊接着調用了init方法對數據進行初始化,NSObject類參考文檔裏也有具體的說明,大家也可以查看文檔,具體實現方式隨後我會用代碼向大家進行展示。
第二種方式看起來就很明確了,先調用alloc創建指針指向內存中的數據結構,再調用init方法初始化數據。這裏需要注意的是,init方法只是起到了初始化數據的作用,其實也可以自定義初始化方法,即完全可以自定義一個普通返回NSObject類型的方法來代替init方法,即init方法是可以隨意被代替的。只不過NSObject類型中new方法默認會調用init方法而已,init方法可以看作是NSObject類型的默認構造函數。
所以綜上所述,其實只有alloc方法是每次必須調用的方法,那麼我們只要控制住alloc方法,對此方法進行覆蓋就可以保證類型對象的單一性了。好了,說了這麼多,讓我們看看如何實現吧。
-
Singleton類接口
1
2
3
4
5
6
|
#import
<Foundation/Foundation.h> @interface
Singleton: NSObject +(Singleton*)GetInstance; -( void )SayHello; @end |
-
Singleton類實現
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
|
#import
"Singleton.h" @implementation
Singleton static
Singleton *myInstance = nil ; static
int
num; +(Singleton*)GetInstance{ @synchronized ([Singleton
class ]){ if (myInstance
== nil ){ myInstance
= [[ self
alloc]init]; } } return
myInstance; } +( id )alloc{ @synchronized ([Singleton
class ]){ if
(myInstance == nil )
{ myInstance
= [ super
alloc]; num++; NSLog (@ "對象數目:%d" ,num); } else
{ NSLog (@ "不好意思,你在實例化第二個對象" ); } return
myInstance; } return
nil ; } -( id )init{ self
= [ super
init]; if ( self
!= nil ){ NSLog (@ "初始化數據" ); } return
self ; } -( void )SayHello{ NSLog (@ "Hello,world!" ); } @end |
-
Main方法調用
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#import
<Foundation/Foundation.h> #import
"Singleton.h" int
main ( int
argc, const
char
*argv[]) { @autoreleasepool { Singleton
*singleton = [Singleton GetInstance]; [singleton
SayHello]; singleton
= [Singleton new ]; [singleton
SayHello]; } return
0; } |
在Main方法中,當調用new方法進行第二次實例化的時候你會發現,Singleton類型的alloc方法第二次被調用了,並打印出“不好意思,你在實例化第二個對象”的語句。至此,不管是調用new方法還是調用alloc方法,還是調用自定義的GetInstance方法都只能生成一個對象實例。