前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅析单例设计模式

浅析单例设计模式

作者头像
VV木公子
修改2021-02-19 10:33:55
7.1K0
修改2021-02-19 10:33:55
举报
文章被收录于专栏:TechBox

在开发中经常会用到单例设计模式,目的就是为了在程序的整个生命周期内,只会创建一个类的实例对象,而且只要程序不被杀死,该实例对象就不会被释放。保证一个类仅有一个实例,并提供一个访问它的全局访问点。

创建单例的几种方式

方式一

传统且正规的方法是把一次性代码dispatch_once写到allocWithZone:方法中去,目的是保证allocWithZone:方法只被调用一次,这样一来,凡是通过[[class alloc] init]方法创建的实例,都是指向同一个对象。代码如下:

代码语言:javascript
复制
+ (instancetype)shareInstance
{
   ALYNetworkManager *instance = [[self alloc] init];
   return instance;
}

static ALYNetworkManager *_instance = nil;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
       _instance = [super allocWithZone:zone];
   });
   return _instance;
}

-(id)copyWithZone:(NSZone *)zone
{
   // 需要遵守NSCopying协议
   return _instance;
}

方式二

更加简单的方式是把一次性代码dispatch_once写到获取单例对象的类方法中去。保证只要通过这个类方法获取的对象都是同一个实例。但是因为没有重写allocWithZone:方法,所以如果有开发者在外部直接调用[[class alloc] init]方法获取实例,那么获取的实例和通过类方法获取的实例就不是同一个实例。这样就不能保证实例的全局唯一性。所以,尤其在多人开发中,采用这种方式存在一定的风险性。代码如下:

代码语言:javascript
复制
+ (ALYNetworkManager *)sharedInstance {
    static ALYNetworkManager *instance;
    static dispatch_once_t token;
    dispatch_once(&token, ^{
        instance = [[ALYNetworkManager alloc]init];
    });
    return instance;
}

如下图,可以看到,通过shareInstance类方法获取的实例始终是同一个,而通过[[class alloc] init] 和 shareInstance类方法获取的实例并不是同一个:

方式三

另外,除了使用一次性代码dispatch_once保证多线程情况下获取的仍然是同一个对象,我们还可以使用同步锁的方式达到这个目的,代码如下:

代码语言:javascript
复制
+ (instancetype)shareInstance {
    static ALYNetworkManager *instance = nil;
    instance = [[ALYNetworkManager alloc] init];
   
    return instance;
}

static ALYNetworkManager *_instance = nil;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    @synchronized (self) {
        if (!_instance) {
            _instance = [super allocWithZone:zone];
        }
    }
    return _instance;
}

验证多线程下获取的是否为同一个实例,如下图:

方式四

当然还可以在单例的全局访问点(类方法)中使用同步锁,其结果和方式二是一样的:外部都不能直接通过调用[[class alloc] init]方法来获取单例,代码如下:

代码语言:javascript
复制
+ (instancetype)shareInstance {
    static ALYNetworkManager *instance = nil;
    @synchronized (self) {
        if (!instance) {
            instance = [[ALYNetworkManager alloc] init];
        }
    }
    return instance;
}

单例工具类的创建

此处以利用dispatch_once一次性代码 + 宏定义的方式抽取出一个通用的单例宏,其实在网上随便一搜,就可以搜到一大把单例宏。

ARC\MRC判断

代码语言:javascript
复制
#if __has_feature(objc_arc)

#else

#endif

宏抽取

代码语言:javascript
复制
#define interfaceSingleton(name)  +(instancetype)share##name


#if __has_feature(objc_arc)
// ARC
#define implementationSingleton(name)  \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
#else
// MRC

#define implementationSingleton(name)  \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (oneway void)release \
{ \
} \
- (instancetype)retain \
{ \
return _instance; \
} \
- (NSUInteger)retainCount \
{ \
return  MAXFLOAT; \
}
#endif

以后如果需要创建单例工具类直接创建一个Singleton.h文件,把上面的代码拷贝到.h文件中。在单例类(拿Person类为例)中导入这个头文件。直接在单例类的.h文件中interfaceSingleton(name)传入参数,.m文件中implementationSingleton(name)传入参数即可。

如下:

代码语言:javascript
复制
/************ALYNetworkManager.h**********/
#import <Foundation/Foundation.h>
#import "Singleton.h"

@interface ALYNetworkManager : NSObject

interfaceSingleton(ALYNetworkManager);

@end

/************ALYNetworkManager.m**********/
#import "ALYNetworkManager.h"

@implementation ALYNetworkManager


implementationSingleton(ALYNetworkManager)

@end

git地址点这里

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.01.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建单例的几种方式
    • 方式一
      • 方式二
        • 方式三
          • 方式四
          • 单例工具类的创建
            • ARC\MRC判断
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档