一、靜態(tài)指針?lè)绞剑▎尉€程模式單例)
創(chuàng)新互聯(lián)公司2013年開(kāi)創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站建設(shè)、成都網(wǎng)站制作網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元特克斯做網(wǎng)站,已為上家服務(wù),為特克斯各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220
二、多線程加鎖單例
三、單例的健壯性
由于水平有限,難免出現(xiàn)紕漏,如有問(wèn)題還請(qǐng)不吝賜教。
為你解答。
第一、基本概念
單例模式是一種常用的軟件設(shè)計(jì)模式。在它的核心結(jié)構(gòu)中只包含一個(gè)被稱為單例類的特殊類。通過(guò)單例模式可以保證系統(tǒng)中一個(gè)類只有一個(gè)實(shí)例而且該實(shí)例易于外界訪問(wèn)。
第二、在IOS中使用單例模式的情況
1.如果說(shuō)創(chuàng)建一個(gè)對(duì)象會(huì)耗費(fèi)很多系統(tǒng)資源,那么此時(shí)采用單例模式,因?yàn)橹恍枰粋€(gè)實(shí)例,會(huì)節(jié)省alloc的時(shí)間
2.在IOS開(kāi)發(fā)中,如果很多模塊都要使用同一個(gè)變量,此時(shí)如果把該變量放入單例類,則所有訪問(wèn)該變量的調(diào)用變得很容易,否則,只能通過(guò)一個(gè)模塊傳遞給另外一個(gè)模塊,這樣增加了風(fēng)險(xiǎn)和復(fù)雜度
第三、創(chuàng)建單例模式的基本步驟
1.聲明一個(gè)單例對(duì)象的靜態(tài)實(shí)例,并初始化為nil
2.聲明一個(gè)類的工廠方法,生成一個(gè)該類的實(shí)例,并且只會(huì)生成一個(gè)
3.覆蓋allcoWithZone方法,確保用戶在alloc 時(shí),不會(huì)產(chǎn)生一個(gè)多余的對(duì)象
4.實(shí)現(xiàn)NSCopying協(xié)議,覆蓋release,autorelease,retain,retainCount方法,以確保只有一個(gè)實(shí)例化對(duì)象
5.在多線程的環(huán)境中,注意使用@synchronized關(guān)鍵字
[cpp] view plaincopyprint?
//
// UserContext.h
// SingleDemo
//
// Created by andyyang on 9/30/13.
// Copyright (c) 2013 andyyang. All rights reserved.
//
#import Foundation/Foundation.h
@interface UserContext : NSObject
@property (nonatomic,retain) NSString *username;
@property(nonatomic,retain)NSString *email;
+(id)sharedUserDefault;
@end
[cpp] view plaincopyprint?
//
// UserContext.m
// SingleDemo
//
// Created by andyyang on 9/30/13.
// Copyright (c) 2013 andyyang. All rights reserved.
//
#import "UserContext.h"
static UserContext *singleInstance=nil;
@implementation UserContext
+(id)sharedUserDefault
{
if(singleInstance==nil)
{
@synchronized(self)
{
if(singleInstance==nil)
{
singleInstance=[[[self class] alloc] init];
}
}
}
return singleInstance;
}
+ (id)allocWithZone:(NSZone *)zone;
{
NSLog(@"HELLO");
if(singleInstance==nil)
{
singleInstance=[super allocWithZone:zone];
}
return singleInstance;
}
-(id)copyWithZone:(NSZone *)zone
{
NSLog(@"hello");
return singleInstance;
}
-(id)retain
{
return singleInstance;
}
- (oneway void)release
{
}
- (id)autorelease
{
return singleInstance;
}
- (NSUInteger)retainCount
{
return UINT_MAX;
}@end
[cpp] view plaincopyprint?
#import Foundation/Foundation.h
#import "UserContext.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
UserContext *userContext1=[UserContext sharedUserDefault];
UserContext *userContext2=[UserContext sharedUserDefault];
UserContext *userContext3=[[UserContext alloc] init];
UserContext *userContext4=[userContext1 copy];
// insert code here...
NSLog(@"Hello, World!");
}
return 0;
}
在開(kāi)發(fā)中我們可以利用ios提供的方法來(lái)實(shí)現(xiàn)單例模式:
SYNTHESIZE_SINGLETON_FOR_CLASS(MyClassName);
將該語(yǔ)句置于@implementation MyClassName聲明后,這樣你的類自動(dòng)會(huì)變成單例。
內(nèi)容來(lái)自于richard_如風(fēng)的博客。
在iOS OC中,一般我們都是用官方推薦的寫(xiě)法來(lái)寫(xiě)單例:GCD方式單例
URLManager* a = [URLManager sharedInstance];
接下來(lái),可以用 a 這個(gè)單例來(lái)干很多事情了,看起來(lái)沒(méi)有問(wèn)題。在很多實(shí)際的項(xiàng)目中,很多人也的確是這么做的。
可是,誰(shuí)能保證所有人都會(huì)使用 sharedInstance 方法來(lái)創(chuàng)建對(duì)象?而一旦有人用 alloc,new 等來(lái)創(chuàng)建對(duì)象,這就不是單例了。
例如:
查看 a、b、c :
可以看到, a、b、c 不是同一個(gè)對(duì)象,而所謂單例,就是不管我用何種方法創(chuàng)建對(duì)象,都必須是同一個(gè) 。
所以,單例模式,絕不是一個(gè) sharedInstance 就夠了。
解決方案 一 、
那么如何避免這種問(wèn)題呢?我們知道:
在對(duì)象創(chuàng)建的時(shí)候,無(wú)論是 alloc 還是 new,都會(huì)調(diào)用到 allocWithZone: 方法;
使用拷貝創(chuàng)建對(duì)象時(shí),會(huì)調(diào)用 copyWithZone:,mutableCopyWithZone:方法;
那么,重寫(xiě)這些方法,就可以讓創(chuàng)建的對(duì)象唯一。
再運(yùn)行,看一看a、b、c:
都是同一個(gè)對(duì)象!大功告成!
解決方案 二 、
此外,還有一種方法,就是直接禁用掉 alloc、new 、copy等方法:
如此,在調(diào)用這些方法時(shí)就會(huì)報(bào)錯(cuò),提示使用 sharedInstance 方法:
以此,也可以達(dá)到單例模式的要求,始終只有一個(gè)對(duì)象。
這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。這種模式涉及到一個(gè)單一的類,該類負(fù)責(zé)創(chuàng)建自己的對(duì)象,同時(shí)確保只有單個(gè)對(duì)象被創(chuàng)建。這個(gè)類提供了一種訪問(wèn)其唯一的對(duì)象的方式,可以直接訪問(wèn),不需要實(shí)例化該類的對(duì)象。
注意
1、單例類只能有一個(gè)實(shí)例。
2、單例類必須自己創(chuàng)建自己的唯一實(shí)例。
3、單例類必須給所有其他對(duì)象提供這一實(shí)例。
VSingleton.h
VSingleton.m
調(diào)用驗(yàn)證
輸出
之前創(chuàng)建單例是使用下面的方式:
這種方式創(chuàng)建的單例,如果外部使用了alloc方法來(lái)創(chuàng)建實(shí)例,或者copy方法拷貝了單例實(shí)例,那么就無(wú)法確保對(duì)象的唯一性,因此需要重寫(xiě)allocWithZone:和copyWithZone:方法來(lái)規(guī)避外部創(chuàng)建多個(gè)單例對(duì)象。
說(shuō)明:
1.在調(diào)用alloc方法時(shí),OC內(nèi)部會(huì)調(diào)用allocWithZone:這個(gè)方法來(lái)申請(qǐng)內(nèi)存.
2.NSObject雖然有copy 和 mutableCopy方法,但是并沒(méi)有實(shí)現(xiàn),需要在子類中遵循NSCopying協(xié)議,即實(shí)現(xiàn)copyWithZone:方法.
在數(shù)學(xué)和邏輯學(xué)中,單例定義為” 有且僅有一個(gè)元素的集合 “,在無(wú)論什么情況下,獲取到的都是同一個(gè)值。在程序中,單例模式保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。這個(gè)方法應(yīng)該是類方法,阻止所有想要生成對(duì)象的訪問(wèn),避免一個(gè)全局使用的類頻繁地創(chuàng)建和銷(xiāo)毀。
static uniqueInstance 是 Singleton 中的唯一實(shí)例, static sharedInstance 將它返回給客戶端。通常, shareInstance 會(huì)檢查 uniqueInstance 是否已經(jīng)被實(shí)例化,如果沒(méi)有,會(huì)生成一個(gè)實(shí)例然后返回 uniqueInstance 。
沒(méi)有接口,不能繼承,與單一職責(zé)原則沖突,一個(gè)類應(yīng)該只關(guān)心內(nèi)部邏輯,而不關(guān)心外面怎么樣來(lái)實(shí)例化。
只要應(yīng)用程序需要集中式的類來(lái)協(xié)調(diào)其服務(wù),這個(gè)類就應(yīng)該生成單一的實(shí)例,而不是多個(gè)實(shí)例。