OC基础-单例设计模式

来源:互联网 发布:网络重置怎么弄 编辑:程序博客网 时间:2024/06/08 06:02

一、概念

单例的概念和JAVA中原理类似,就是在整个程序声明周期中,该对象始终只有一份保存在内存中。单例对象是全局变量,方便数据共享。


二、单例的经典写法

static id sharedMyManager; +(id)sharedThemeManager{    if(sharedMyManager == nil){        sharedMyManager = [[self alloc] init];    }    return sharedMyManager; }
需要有一个全局的类的对象,在单例方法中,第一次调用该方法时,实例化该对象,以后每一次调用都返回该对象。多个指针指向同一内存空间。

单例的方法命名规范:

shared/default/current+类名


三、经典单例模式的一个例子

#import <Foundation/Foundation.h>//主题管理器@interface ThemeManager : NSObject{    //主题名称    NSString * _name;}@property(nonatomic, retain)NSString * name;//单例方法+(id)sharedThemeManager;@end#import "ThemeManager.h"//声明一个全局的该类的对象static ThemeManager * manager;@implementation ThemeManager//实现setter和getter@synthesize name = _name;//实现单例的方法+(id)sharedThemeManager{    if(manager == nil){        //manager = [[self alloc] init];        //只有第一次调用该方法的时候,才会创建对象的实例,并将该对象保存为全局变量,之后每一次调用该方法,都返回这个全局变量。        manager = [[[self class] alloc] init];    }    return manager;}-(id)init{    self = [super init];    if(self){        self.name = [NSString stringWithFormat:@"Default"];        //使用Default作为初始化的name,取代nil    }    return self;}-(NSString *)description{    return [NSString stringWithFormat:@"Theme name is %@", self.name];}-(void)dealloc{    [_name release];    _name = nil;    [super dealloc];}@end#import <Foundation/Foundation.h>#import "ThemeManager.h"int main(int argc, const char * argv[]) {    @autoreleasepool {        //使用单例创建两个对象,这里虽然使用alloc也没问题,但不建议这么做。既然是单例模式,就按照单例的规范来写        ThemeManager * tm1 = [ThemeManager sharedThemeManager];        ThemeManager * tm2 = [ThemeManager sharedThemeManager];        tm2.name = @"夏日倾情";        //使用%p输出对象的内存地址,结果是相同的,也就是两个对象指向同一内存空间。        NSLog(@"tm1 is %p, tm2 is %p", tm1, tm2);                //这里由于默认的name是nil,我们可以重写init来修改这个值        NSLog(@"tm1:%@,tm2:%@", tm1, tm2);            }    return 0;}

四、单例模式的其他写法

1.经典单例模式的缺陷

经典单例模式,是工业级写法,但是有一个缺陷。如果有两个线程,同时调用了该单例方法,就有可能同时满足if(manager == nil)条件,创建了2个对象,造成内存泄露,是 非线程安全的。

2.加锁写法

类似java中的加锁写法

static ThemeManager * manager;+(id)sharedThemeManager{    //加锁,锁为self    @synchronized(self) {        if(manager == nil){            manager = [[self alloc] init];        }    }    return manager;}
3.免锁写法

//免锁写法,Lock Free//该方法只在类的对象第一次alloc的时候调用,有且只调用一次。+ (void)initialize{    static BOOL initialized = NO;    if (initialized == NO) {        initialized = YES;        manager = [[self alloc] init];    }}
4.GCD写法

+(id)sharedThemeManager{    static dispatch_once_t once;    dispatch_once(&once, ^{        manager = [[self alloc] init];    });    return manager;}

该写法,保证了即使有多个线程,{}代码块也只执行一次。

最常用的写法:经典写法、加锁写法、GCD写法


@诗未冷学习博客


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 光猫没有wan口怎么办 usb无线网卡坏了怎么办 wifi接收器电脑不识别怎么办 无线路由接收器识别不了怎么办 小米3一直闪红灯怎么办 手机拨号键删了怎么办 联想笔记本电脑无线网卡坏了怎么办 联想z360内置无线网卡坏怎么办 usb无线网卡驱动安装失败怎么办 无线网被禁用了怎么办 未连接无线通信已关闭怎么办 手机设置路由器打不开了怎么办 手机打不开登录路由器的网址怎么办 按了光猫复位后怎么办 按了猫的复位键怎么办 望远镜的镜片小水雾是怎么办 坚果r1不断重启怎么办 忘记Wi-Fi密码了怎么办 魅蓝手机null锁住了怎么办 红米手机锁屏了怎么办 不记得锁屏密码怎么办 小米手机音量键坏了怎么办 小米6音量键坏了怎么办 小米2s开不开机怎么办 小米4不充电了怎么办 小米2开不开机怎么办 手机开机键开不了机怎么办 三星s4反复重启怎么办 小米5反复重启怎么办 电脑系统奔溃了怎么办 电脑开机后屏幕出现英文怎么办 小米4开不开机了怎么办 小米4一直显示mi怎么办 小米手机开关键失灵怎么办 小米手机开机键失灵怎么办 小米6不断重启怎么办 小米6一直重启怎么办 小米6自动重启怎么办 手机的开机键坏了怎么办 小米6频繁重启怎么办 小米6安装xp卡米怎么办