玩转iOS开发:《iOS设计模式 — 单例模式》
目录
作者感言
有一段时间没有发博客了, 刚好现在忙完项目的需求, 现在可以闲下来写写简书, 顺便自己给自己复习巩固一下知识, 不过我在这里又要吐槽一句, 项目中遇到了一个单例的问题, 让我感到非常的蛋疼, 写这个单例的人只是单纯了为了写单例而写单例, 没有想到会发生什么, 现在让我们一起来看看什么叫单例吧.
最后:
如果你有更好的建议或者对这篇文章有不满的地方, 请联系我, 我会参考你们的意见再进行修改, 联系我时, 请备注单例模式
如果觉得好的话, 希望大家也可以打赏一下嘻嘻祝大家学习愉快谢谢
Cain(罗家辉)
联系方式: zhebushimengfei@qq.com
腾讯QQ: 350116542
简介
这是一张单例的
UML
图, 非常简单明了的讲解单例类到底是怎么回事, 通常单例是用来作为管理中心, 或者是通知中心, 比如在iOS
当中的NSNotificationCenter
,[[UIApplication sharedApplication] statusBarStyle]
,NSUserDefaults
,[NSFileManager defaultManager]
等等都是单例, 单例类有几个特征.
- 系统当中只有一个实例
- 易于外界访问
- 防止子类继承
- 共享信息
准备工作
首先, 我们先来建一个
WorkSpace
, 这样子方便我们以后多添加工程, 因为单例模式只是我们的开始.
添加单例工程
创建完
WorkingSpace
之后, 我们就来添加SingletonPattern(单例)
的工程
创建单例类
现在我们来创建一个叫
UserInfoManager
单例类
声明一个类方法用于外界访问
#import <Foundation/Foundation.h>
@interface UserInfoManagerCenter : NSObject
+ (instancetype)managerCenter;
@end
接下来我们去实现这个类方法就好了
#import "UserInfoManagerCenter.h"
static UserInfoManagerCenter *managerCenter = nil;
@implementation UserInfoManagerCenter
+ (instancetype)managerCenter {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
managerCenter = [[UserInfoManagerCenter alloc] init];
});
return managerCenter;
}
看起来, 我们好像搞定了整个单例模式了, 下面让我们来试试效果.
#import "ViewController.h"
#import "UserInfoManagerCenter.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UserInfoManagerCenter *infoManagerCenter = [UserInfoManagerCenter managerCenter];
UserInfoManagerCenter *managerCenter = [UserInfoManagerCenter managerCenter];
NSLog(@"%@", infoManagerCenter);
NSLog(@"%@", managerCenter);
}
@end
打印出来的效果好像是只有一个, 但实际上并不是的, 我们再来看看
#import "ViewController.h"
#import "UserInfoManagerCenter.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UserInfoManagerCenter *infoManagerCenter = [UserInfoManagerCenter managerCenter];
UserInfoManagerCenter *managerCenter = [UserInfoManagerCenter managerCenter];
UserInfoManagerCenter *userInfoManagerCenter = [[UserInfoManagerCenter alloc] init];
NSLog(@"%@", infoManagerCenter);
NSLog(@"%@", managerCenter);
NSLog(@"%@", userInfoManagerCenter);
}
@end
发现这个类还是可以初始化的, 并且是另外开辟了内存空间来存储的, 这就很尴尬了, 说好的只有一个实例呢???
添加唯一单例判断
我在这里说一句, 施主莫怕, 等贫僧跳大, 继续回到单例类当中, 添加几个判断就好了
#import "UserInfoManagerCenter.h"
static UserInfoManagerCenter *managerCenter = nil;
@implementation UserInfoManagerCenter
+ (instancetype)managerCenter {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
managerCenter = (UserInfoManagerCenter *)@"UserInfoManagerCenter";
managerCenter = [[UserInfoManagerCenter alloc] init];
});
NSString *classString = NSStringFromClass([self class]);
if ([classString isEqualToString:@"UserInfoManagerCenter"] == NO) {
NSParameterAssert(nil);
}
return managerCenter;
}
- (instancetype)init {
NSString *userInfomanagerCenter = (NSString *)managerCenter;
if ([userInfomanagerCenter isKindOfClass:[NSString class]] && [userInfomanagerCenter isEqualToString:@"UserInfoManagerCenter"]) {
if (self = [super init]) {
// 这里直接什么都不做操作
}
return self;
}
return nil;
}
@end
口说无凭, 我们来看看运行效果
这下子, 可以说明是只有一个实例了吧, 下面再来看看子类是否能继承
#import "ViewController.h"
#import "UserInfoManagerCenter.h"
#import "SubUserInfoManagerCenter.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UserInfoManagerCenter *infoManagerCenter = [UserInfoManagerCenter managerCenter];
UserInfoManagerCenter *managerCenter = [UserInfoManagerCenter managerCenter];
UserInfoManagerCenter *userInfoManagerCenter = [[UserInfoManagerCenter alloc] init];
SubUserInfoManagerCenter *subUserInfoManagerCenter = [SubUserInfoManagerCenter managerCenter];
NSLog(@"%@", infoManagerCenter);
NSLog(@"%@", managerCenter);
NSLog(@"%@", userInfoManagerCenter);
NSLog(@"%@", subUserInfoManagerCenter);
}
@end
好了, 现在单例所需的
- 易于外界访问
- 系统当中只有一个实例
- 防止子类继承
我们都搞定, 酱紫我们就完成了一个单例类的创建啦
工程地址:
https://github.com/CainRun/DesignPattern/tree/master/SingletonPattern