Objective C 單例模式

顧名思義,單例模式的特點就是保證一個類僅有一個實例。因爲這個模式只和一個類有關,沒有類與類之間的關係,所有就不給出圖示了。那麼還是先說一下基本的定義。

單例模式(Singleton),保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

通常我們可以讓一個全局變量使得一個對象被訪問,但它不能防止你實例化多個對象。一個最好的辦法就是,讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例可以被創建,並且它可以提供一個訪問該實例的方法。平時,我們常用單例模式的地方通常是多線程。

因爲Objective C傳承了Smalltalk語言,所以在Objective C中實現單例模式和C++和C#以及Java都不太一樣。因爲要保證類型對象的單一性,所以就要考慮Objective C在實例化對象時候的各種方式。因爲在Objective C中創建的各個類型都繼承自NSObject類型,所以我們需要考慮NSObject類型裏實例化的方法,下面讓我們展開來說。

在Objective C的實例化對象的方式主要有三種,分別如下:

  1. obj = [NSObject new];

  2. obj = [[NSObject alloc]init];

  3. 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方法都只能生成一個對象實例。


發佈了37 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章