1. 程式人生 > >iOS開發單例模式(懶漢模式&惡漢模式)

iOS開發單例模式(懶漢模式&惡漢模式)

1.單利模式概述

單例模式是iOS常用設計模式中的一種。單例設計模式的作用是使得這個類的一個物件成為系統中的唯一例項,因此需要用一種唯一的方法去建立這個物件並返回這個物件的地址。那麼,我們何時使用單例模式呢?1、類只能有一個例項,而且必須從一個為人熟知的訪問點對其訪問。2、這個唯一的例項只能通過子類化進行擴充套件,而且擴充套件的物件不會破壞客戶端程式碼。

n單例模式的作用p可以保證在程式執行過程,一個類只有一個例項,而且該例項易於供外界訪問p從而方便地控制了例項個數,並節約系統資源pn單例模式的使用場合p在整個應用程式中,共享一份資源(這份資源只需要建立初始化1次)pn單例模式在ARC\MRC環境下的寫法有所不同
需要編寫2套不同的程式碼p可以用巨集判斷是否為ARC環境

#if __has_feature(objc_arc)

// ARC

#else

// MRC

#endif

nARC中,單例模式的實現p.m中保留一個全域性的static的例項

static id_instance;

p重寫allocWithZone:方法,在這裡建立唯一的例項(注意執行緒安全)

+ (id)allocWithZone:(struct _NSZone*)zone

{

   @synchronized(self) {

        if (!_instance) {

            _instance = [super allocWithZone

:zone];

        }

   }

   return _instance;

}

p提供1個類方法讓外界訪問唯一的例項

+ (instancetype)sharedSoundTool

{

   @synchronized(self) {

        if (!_instance) {

            _instance = [[self alloc] init];

        }

   }

   return _instance;

}

p實現copyWithZone:方法

- (id)copyWithZone:(struct _NSZone*)zone

{

   return _instance;

}

n
ARC中(MRC),單例模式的實現ARC多了幾個步驟)p實現記憶體管理方法

- (id)retain { return self; }

- (NSUInteger)retainCount { return 1; }

- (oneway void)release{}

- (id)autorelease { return self; }

2.單利模式之懶漢模式

2.1懶漢式例項

首先建立一個project,然後建立一個HMMusicTool類來演示懶漢式
#import <Foundation/Foundation.h>

@interface HMMusicTool : NSObject
+ (instancetype)sharedMusicTool;//寫這個方法共享單例物件
@end

#import "HMMusicTool.h"

@implementation HMMusicTool
/**
 static : 修飾變數
 1> 修飾全域性變數
 * 全域性變數的作用域僅限於當前檔案內部(其意義是,防止該全域性變數被別人修改,只有檔案內部才有權利修改)
 
 2> 修飾區域性變數 :
 * 區域性變數的生命週期 跟 全域性變數 類似
 * 但是不能改變作用域
 * 能保證區域性變數永遠只初始化1次,在程式執行過程中,永遠只有1份記憶體
 */

static id _instance; //全域性變數,防止該全域性變數被別人修改,只有檔案內部才有權利修改(永遠只有一份記憶體)

/**
 *  當呼叫alloc方法的時候,alloc方法內部會呼叫這個方法
 */
+ (id)allocWithZone:(struct _NSZone *)zone
{
    if (_instance == nil) { // 防止頻繁加鎖
        @synchronized(self) {  //加鎖防止多執行緒同步的時候大家都建立物件
            if (_instance == nil) { // 防止建立多次
                _instance = [super allocWithZone:zone];
            }
        }
    }
    return _instance;
}

+ (instancetype)sharedMusicTool //寫這個方法共享單例物件

{
    if (_instance == nil) { // 防止頻繁加鎖  保證init方法也只調用一次
        @synchronized(self) {
            if (_instance == nil) { // 防止建立多次
                _instance = [[self alloc] init];
            }
        }
    }
    return _instance;
}

//- (id)copyWithZone:(NSZone *)zone
//{
//    return _instance;
//}
@end

此時在控制器中使用這個類
#import "htingViewController.h"
#import"HMMusicTool.h"
@interface htingViewController ()

@end

@implementation htingViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
         HMMusicTool *tool = [[HMMusicTool alloc] init];
        HMMusicTool *tool2 = [[HMMusicTool alloc] init];
       HMMusicTool *tool3 = [HMMusicTool sharedMusicTool];
       HMMusicTool *tool4 = [HMMusicTool sharedMusicTool];
    NSLog(@"%@ %@ %@ %@",tool,tool2,tool3,tool4);
}
@end

列印結果:
單例模式[625:607] <HMMusicTool: 0x8f3d430> <HMMusicTool: 0x8f3d430> <HMMusicTool: 0x8f3d430> <HMMusicTool: 0x8f3d430>

可以發現列印結果都是同一個物件

2.2懶漢式剖析(優缺點及實現機制)

2.2.1實現機制

1⃣️當呼叫alloc方法的時候,alloc方法內部會呼叫allocWithZone:這個方法
2⃣️提供一個share方法,如上例項

2.2.2優缺點

從執行緒安全性上講,不加同步的懶漢式是執行緒不安全的,比如,有兩個執行緒,一個是執行緒A,一個是執行緒B,它們同時呼叫alloc方法,那就可能導致併發問題。如上例項 可以加鎖防止多執行緒同步的時候大家都建立物件。

懶漢式是典型的時間換空間,也就是每次獲取例項都會進行判斷,看是否需要建立例項,浪費判斷的時間。當然,如果一直沒有人使用的話,那就不會建立例項,則節約記憶體空間。


3.單例模式之惡漢模式

3.1新建一個HMSoundTool類演示惡漢模式

#import <Foundation/Foundation.h>

@interface HMSoundTool : NSObject
+ (instancetype)sharedSoundTool;
@end

//  餓漢式

#import "HMSoundTool.h"

@implementation HMSoundTool
static id _instance;

/**
 *  當類載入到OC執行時環境中(記憶體),就會呼叫一次(一個類只會載入1次)
 */
+ (void)load
{
    _instance = [[self alloc] init];
}

+ (id)allocWithZone:(struct _NSZone *)zone
{
    if (_instance == nil) { // 防止建立多次
        _instance = [super allocWithZone:zone];
    }
    return _instance;
}

+ (instancetype)sharedSoundTool
{
    return _instance;
}



@end

控制器
//  htingViewController.m


#import "htingViewController.h"
#import"HMSoundTool.h"
@interface htingViewController ()

@end

@implementation htingViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    HMSoundTool *tool1 = [HMSoundTool sharedSoundTool];
    HMSoundTool *tool3 = [HMSoundTool sharedSoundTool];
    HMSoundTool *tool4 = [[HMSoundTool alloc] init];
    NSLog(@"%@ %@ %@ ", tool1,  tool3, tool4);
}
@end
列印結果

餓漢模式[1968:607] <HMSoundTool: 0x8e11770> <HMSoundTool: 0x8e11770> <HMSoundTool: 0x8e11770> 

3.2惡漢模式剖析(優缺點及實現機制)

3.2.1實現機制

當類載入到OC執行時環境中(記憶體),就會呼叫+ (void)load一次(一個類只會載入1次)


3.2.2 優缺點

餓漢式是執行緒安全的,因為虛擬機器保證只會裝載一次,在裝載類的時候是不會發生併發的。