文章导航PC6首页软件下载单机游戏安卓资源苹果资源

pc软件新闻网络操作系统办公工具编程服务器软件评测

安卓新闻资讯应用教程刷机教程安卓游戏攻略tv资讯深度阅读综合安卓评测

苹果ios资讯苹果手机越狱备份教程美化教程ios软件教程mac教程

单机游戏角色扮演即时战略动作射击棋牌游戏体育竞技模拟经营其它游戏游戏工具

网游cf活动dnf活动lol周免英雄lol礼包

手游最新动态手游评测手游活动新游预告手游问答

您的位置:首页单机游戏角色扮演 → 怪物猎人世界新装备介绍 怪物猎人世界新装备新系统一览

iOS开发单例使用问题

翻译、修改自obj.io

单例(Singletons),是Cocoa的核心模式之一。在iOS上,单例十分常见,比如:UIApplication,NSFileManager等等。虽然它们用起来十分方便,但实际上它们有许多问题需要注意。所以在你下次自动补全dispatch_once代码片段的时候,想一下这样会导致什么后果。

在《设计模式》一书中给出了单例的定义:

单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式提供了一个访问点,供客户类为共享资源生成唯一实例,并通过它来对共享资源进行访问,这一模式提供了灵活性。

在objective-c中,可以使用以下代码创建一个单例:

+(instancetype)sharedInstance

{

static dispatch_once_t once;

static id sharedInstance;

dispatch_once(&once, ^{

sharedInstance = [[self alloc]init];

});

return sh易语言超文本浏览框_最强资讯网aredInstance;

}

当类只能有一个实例,而且必须从一个访问点对其进行访问时使用单例就显得十分方便,因为使用单例保证了访问点的唯一、一致且为人熟知。

全局状态

首先我们都应该达成一个共识"全局可变状态"是危险的,因为这样会让程序变得难以理解和调试,就削减状态性代码上,面向对象编程应该向函数式编程学习。

比如下面的代码:

@implementation Math{

NSUInteger _a;

NSUInteger _b;

-(NSUInteger)computeSum

return _a + _b;

这段代码想要计算_a和_B相加的和,并返回。但事实上这段代码存在着不少问题:

computeSum方法中并没有把_a和_b作为参数。相bootstrap ppt特效插件_最强资讯网比查找interface并了解哪个变量控制方法jquery时间格式化插件下载_最强资讯网的输出,查找implementation来了解显得更隐蔽,而隐蔽代表着容易发生错误。

当准备修改_a和_b的值来让它们调用computeSum方法的时候,程序员必须清楚修改它们的值不会影响其他包含着两个值的代码的正确性,而在多线程的情况下作jquery easyui form同步_最强资讯网出这样的判断显得尤其困难。

对比下面这段代码:

+(NSUInteger)computeSumOf:(NSUInteger)a plus:(NSUInteger)b

return a + b;

这段代码中,a和b的从属显得十分清晰,不再需要去改变实例的状态来调用这个方法,而且不用担心调用这个方法的副作用。

那这个例子和单例又有什么关系呢?事实上,单例就是披着羊皮的全局状态。一个单例可以在任何地方被使用,而且不用清晰地声明从属。程序中的任何模块都可以简单的调用[MySingleton sharedInstance],然后拿到这个单例的访问点,这意味着任何和单例交互时产生的副作用都会有可能影响程序中随机的一段代码,如:

@interface MySingleton : NSObject

+(instancetype)sharedInstance;

-(NSUInteger)badMutableState;

-(void)setBadMutableState:(NSUInteger)badMutableState;

@end

@implementation ConsumerA

-(void)someMethod

if([[MySingleton sharedInstance] badMutableState]){

//do something...

@implementation ConsumerB

-(void)someOtherMethod

[[MySingleton sharedInstancjavascript关键词_最强资讯网e] setBadMutableState:0];

在上面的代码中,ConsumerA和ComsumerB是程序中两个完全独立的模块,但是ComsumerB中的方法会影响到ComsumerA中的行为,因为这个状态的改变通过单例传递了过去。

在这段代码,正是因为单例的全局性和状态性,导致了ComsumerA和ComsumerB这两个看起来似乎毫无关系的模块之间隐含的耦合。

另一个单例的主要问题是它们的生命周期。

举个例子,假设一个app中需要实现能够让用户看到他们的好友列表的功能,每一个好友有自己的头像,同时我们还希望这个app能够下载并缓存这些好友的头像。这时候通过之前学习单例的知识,我们很可能会写出以下的代码:

@interface MyAppCache : NSObject

+(instancetype)sharedCMyAppCache;

-(void)cacheProfileImage:(NSData *)imageData forUserId:(NSString *)userID;

-(NSData *)cachedProfileImageForUserId:(NSString *)userId;

这段代码看起来完全没有问题,运行起来也很好,所以aecshop发布接口_最强资讯网pp继续开发,直到有一天,我们决定帮app加入"登出"的功能。突然我们发现,用户数据储存在全局单例中。当用户登出的时候,我们想要把这些数据清除掉,当新用户登入的时候,再为他创建一个新的MyAppCache。

但是问题出在了单例这里,因为单例的定义就是:"创建一次,永久存活"的实例。事实上有很多方法解决上面的问题,我们也许可以在用户登出的时候销毁这个单例:

static MyAppCache *myAppCache;

+(instancetype)sharedMyAppCache

if(!myAppCache)

myAppCache = [[self alloc] init];

return myAppCache;

+(void)tearDown

myAppCache = nil;

上面的代码扭曲了单例这个模式,但是能起到作用。

事实上的确可以使用这个方法来解决这个问题,但是代价太大了。最重要的一点是我们放弃了dispatch_once,而它正是保证了方法调用时候的线程安全,现在所有调用[MyAppCache shareMyAppCache]的代码都会得到同一个变量,着需要清楚使用MyAppCache代码执行的顺序。试想一下当用户在登出的时候碰巧后台调用了这个方法来保存图片。

另一方面,实行这个方法需要确保tearDown这个方法不会在后台任务还没执行完成的时候调用,或者说确保执行tearDown方法的时候后台任务都会被取消。否则另一个新的MyAppCache将会创建,并把陈旧的数据保存进去。

但是由于单例没有明确的owner(因为单例自己管理自己的生命周期),销毁一个单例是非常艰难的。

所以这时你可能会想,"那就不要把MyAppCache做成单例吧!"其实问题在于一个对象的生命周期在项目初期可能没有办法很好的确定,如果假设一个对象的生命周期将会匹配整个程序的生命周期,这将会大大限制了代码的可拓展性,当产品需求改动的时候这将会很痛苦。

所以上面的一切都是为了阐明一个观点:"单例只应该保持全局状态,且该状态的生命周期与程序的生命周期一致"。对于程序中已经存在的单例,需要批判性的审阅。

关于这一部分原文中放到了上一章节中提及,但我认为在软件开发中测试是十分重要的一环,所以单独把这一块的内容另开一个章节,并加入一些个人的见解。

由于单例一直在整个app的生命周期中存活着,甚至在执行测试的时候也一直存活着,这导致了在一个测试或许会影响另一个测试,这是在单元测试中的大忌。

所以有必要在进行单元测试的时候能够有效销毁一个单例,并保持住单例线程安全的特性。但在上文中我提到:

"但是由于单例没有明确的owner(因为单例自己管理自己的生命周期),销毁一个单例是非常艰难的。"

似乎两者在自相矛盾,其实不然,可以选择简化单例,与其拥有各种的单例,不如只拥有一个"真正的" 单例ServiceRegistry,而把其他"潜在的"单例来被ServiceRegistry引用,这样其他单例拥有了一个owner,能够在进行单元测试的时候能够及时对单例进行销毁,保证了单元测试的独立性。

另一方面,ServiceRegistry的存在使得其他"单例"不再是单例,这样在TDD的时候会让之前难以 mock 的单例变得更加简单的 mock 。

我们都知道全局可变状态是不好的,但是在使用单例的时候我们又不经意地把它变成我们讨厌的全局可变状态。

在面向对象编程中,我们需要尽可能减少可变状态的作用域,而单例与这个思想背道而驰,希望在下一次使用单例的时候能够多想一想,考虑是否这个变量真正值得成为一个单例,如果不是,还请使用"依赖注入模式"来代替。

CocoaChina开发者社区本着为广大移动开发者提供资讯、问答服务,现向广大开发者们征稿,欢迎有写作爱好和生活经历的开发者们踊跃投稿,来稿范围可设计行业动态,技术相关,产品应用等等,体裁篇幅不限。本征稿启事长期有效。投稿请发送到:

当前文章:http://333179431.emilyseyelive.com/20180216/fa981_10946.html

发布时间:2018-04-22 07:31:47

电脑升级win10无限重启  python如何读取视频文件  xp无法访问win10共享  ios9更新emoji表情在哪里  win10玩游戏卡的一b  jquery get http 请求  linux操作系统安装 iso文件  thinkphp 当前时间加5天  网站seo优化微博加粉推广  python not in (  python 包 反编译工具  php删除文件夹和文件夹包含的所有  ios手机app应用开发  chrome flash player    

相关阅读 【嘉兴楼市·资讯】2017?转动绿色地球第二届"浙江信达地产"环南湖自行车骑...最新1分,2分,5分硬币价格表!你家里的分币值多少钱?甲方乙方之我们是做什么的?工控的搬砖人-云工控冬坝摄影小记-将军泡子上的策马奔腾公示|体育代表队学生骨干换届名单公示直销产品这么好,为什么不去医院销售?今天给你答案!熬夜损害肝脏?看了这些99%的人都不熬夜了2017两大赛事冠军揭晓,数名国际大咖专业点评!

文章评论
发表评论

热门文章 直男究竟喜欢怎样的女孩子?土地使用权续期无需补费?温州:会造成国资流失漳州市开展紧急医学救援技能竞赛黔东南彪悍特色菜凉拌生猪血,你够胆吃吗?

最新文章 黄小蕾怒斥迪士尼工作人员,工作人员反称她无理取闹,到底谁错?看人民的名义?这个帐号天天送爱奇艺VIP会员!速速了解! 卫生间漏水不拆瓷砖应该怎么处理呢?老师傅是这么说的!在合肥注册公司后年检的时候需要提交哪些资料呢?2017五一放假安排时间表高速公路免费通行范围放假安排攻略怎么休最合理?为什么京东唯品会联手"碰瓷"阿里?

人气排行 竞赛征集丨2017第11届澳门设计双年展正式征集骨头汤补钙宝宝长得高?妈妈别错下去了!黄金日元斗志昂扬向前冲,背后罪魁祸首是谁?健康长寿秘方:豆腐海带味增汤有这么大的功效?相恋八年"所托非人"?看春娇志明自己的爱情自己救!大清银币为何价值百万?你知道吗?紧急避孕药不能频繁吃,一年最好只吃两次淘宝客新手如何做到真正盈利?

http://www.i4lourdes.comhttp://www.djanthonyc.comhttp://www.rsflower.comhttp://www.caseylpeek.comhttp://www.brutonian.comhttp://www.pigeondvds.comhttp://www.bbchn.comhttp://www.askarindo.comhttp://www.amysaflar.comhttp://www.alitlbetr.comhttp://www.4008198198.comhttp://beolad.ushttp://swcucm.ushttp://wqcovv.ushttp://zdyvnv.ushttp://wolvou.ushttp://www.fzrs188.comhttp://bnetdj.ushttp://www.ykhruj.ushttp://www.chinabeidun.comhttp://www.ohuaih.ushttp://www.cddongdi.comhttp://www.cbd518.comhttp://gcygcu.ushttp://www.0572gz.comhttp://www.huataiyinwu.cnhttp://www.uoaoi.ushttp://www.dobhw.ushttp://www.ikauq.ushttp://www.ulcyo.ushttp://www.piypi.ushttp://www.gqbsn.ushttp://www.cdqkt.cnhttp://www.airforceonelow-br.cnhttp://www.340c.cnhttp://www.jzycw.cnhttp://www.333tt.cnhttp://www.jiaolingjiu.cnhttp://www.f4gcc.cnhttp://www.358ms.cnhttp://www.yxxsd.cnhttp://www.eqqh.com.cnhttp://www.hg2cc.cnhttp://www.f4g.ushttp://www.gxlzccx.cnhttp://www.bagsleader.comhttp://www.ccllww.comhttp://www.chengdu-huidian.comhttp://www.saifankczy.comhttp://www.zhongyaqd.com