重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
一、静态指针方式(单线程模式单例)
创新互联公司2013年开创至今,是专业互联网技术服务公司,拥有项目成都网站建设、成都网站制作网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元特克斯做网站,已为上家服务,为特克斯各地企业和个人服务,联系电话:028-86922220
二、多线程加锁单例
三、单例的健壮性
由于水平有限,难免出现纰漏,如有问题还请不吝赐教。
为你解答。
第一、基本概念
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问。
第二、在IOS中使用单例模式的情况
1.如果说创建一个对象会耗费很多系统资源,那么此时采用单例模式,因为只需要一个实例,会节省alloc的时间
2.在IOS开发中,如果很多模块都要使用同一个变量,此时如果把该变量放入单例类,则所有访问该变量的调用变得很容易,否则,只能通过一个模块传递给另外一个模块,这样增加了风险和复杂度
第三、创建单例模式的基本步骤
1.声明一个单例对象的静态实例,并初始化为nil
2.声明一个类的工厂方法,生成一个该类的实例,并且只会生成一个
3.覆盖allcoWithZone方法,确保用户在alloc 时,不会产生一个多余的对象
4.实现NSCopying协议,覆盖release,autorelease,retain,retainCount方法,以确保只有一个实例化对象
5.在多线程的环境中,注意使用@synchronized关键字
[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;
}
在开发中我们可以利用ios提供的方法来实现单例模式:
SYNTHESIZE_SINGLETON_FOR_CLASS(MyClassName);
将该语句置于@implementation MyClassName声明后,这样你的类自动会变成单例。
内容来自于richard_如风的博客。
在iOS OC中,一般我们都是用官方推荐的写法来写单例:GCD方式单例
URLManager* a = [URLManager sharedInstance];
接下来,可以用 a 这个单例来干很多事情了,看起来没有问题。在很多实际的项目中,很多人也的确是这么做的。
可是,谁能保证所有人都会使用 sharedInstance 方法来创建对象?而一旦有人用 alloc,new 等来创建对象,这就不是单例了。
例如:
查看 a、b、c :
可以看到, a、b、c 不是同一个对象,而所谓单例,就是不管我用何种方法创建对象,都必须是同一个 。
所以,单例模式,绝不是一个 sharedInstance 就够了。
解决方案 一 、
那么如何避免这种问题呢?我们知道:
在对象创建的时候,无论是 alloc 还是 new,都会调用到 allocWithZone: 方法;
使用拷贝创建对象时,会调用 copyWithZone:,mutableCopyWithZone:方法;
那么,重写这些方法,就可以让创建的对象唯一。
再运行,看一看a、b、c:
都是同一个对象!大功告成!
解决方案 二 、
此外,还有一种方法,就是直接禁用掉 alloc、new 、copy等方法:
如此,在调用这些方法时就会报错,提示使用 sharedInstance 方法:
以此,也可以达到单例模式的要求,始终只有一个对象。
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
VSingleton.h
VSingleton.m
调用验证
输出
之前创建单例是使用下面的方式:
这种方式创建的单例,如果外部使用了alloc方法来创建实例,或者copy方法拷贝了单例实例,那么就无法确保对象的唯一性,因此需要重写allocWithZone:和copyWithZone:方法来规避外部创建多个单例对象。
说明:
1.在调用alloc方法时,OC内部会调用allocWithZone:这个方法来申请内存.
2.NSObject虽然有copy 和 mutableCopy方法,但是并没有实现,需要在子类中遵循NSCopying协议,即实现copyWithZone:方法.
在数学和逻辑学中,单例定义为” 有且仅有一个元素的集合 “,在无论什么情况下,获取到的都是同一个值。在程序中,单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。这个方法应该是类方法,阻止所有想要生成对象的访问,避免一个全局使用的类频繁地创建和销毁。
static uniqueInstance 是 Singleton 中的唯一实例, static sharedInstance 将它返回给客户端。通常, shareInstance 会检查 uniqueInstance 是否已经被实例化,如果没有,会生成一个实例然后返回 uniqueInstance 。
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
只要应用程序需要集中式的类来协调其服务,这个类就应该生成单一的实例,而不是多个实例。