@synchronized(self) { if (sharedInstance == nil) sharedInstance = [[MySingleton alloc] init]; } return sharedInstance;
这基本上是单线程访问单例,如果它是在操作中经常使用的东西,看起来像是可能导致线程不必要地竞争的东西.
@interface MySingleton : NSObject { } + (void)doSomething; @end @implementation MySingleton + (void)initialize { //do some setup if necessary } + (void)doSomething { //do something } @end
通过这种方式,我们避免每次想要引用单例对象时都进行锁定检查,并且我们也可以消除必须将其存储在本地或方法ivar中.
此方法还允许运行时保证在任何给定时间系统中只存在一个实例(Class对象).
编辑
这里除了线程之外还有更多,使用传统的单例,您通常会编写如下代码:
MySingleton *instance = [MySingleton getSharedInstance]; NSObject *someResult = [instance getResult]; //or if (instance.someProperty) { //do something }
但是,如果你的单例是一个类实例,你基本上就不需要一直调用getSharedInstance.考虑以下代码:
NSObject *someResult = [MySingleton getResult]; //or if ([MySingleton someProperty]) { //do something }
我听说你必须将数据存储在文件本地静态变量或全局变量(yuck)中.但它确实与传统的单例不同,除了你丢失了Objective-C 2.0属性(而是必须使用传统的访问器方法).
这对我来说是一个关键的权衡,似乎是一场胜利.在传统的单例中你最终会覆盖-copyWithZone,allocWithZone,-retain,-retainCount,-release和-autorelease,如果你真的想要把事情弄清楚的话.
每次想要编写一个简单的Singleton对象时,这似乎都是很多工作(它们恰好非常有用).那么为什么不简单地用它替换它:
@implementation MySingleton + (void)initialize { //do your setup } - (id)init { NSAssert(NO,@"You should read the documentation on singletons."); } @end
它在代码方面要轻得多,除非你的消费者真的偷偷摸摸,否则他们不会创建两个实例.
已经达到了目的
我的问题是这样的:
使用Class对象作为单例的实例有什么缺点吗?
看起来你可以在线程安全性,内存效率等方面采取所有相同的步骤,而不必记住覆盖如此多的方法和访问器,或者使用实例检查来丢弃代码.
解决方法
我认为有一种可能有用的混合解决方案.
我想在没有调用“getSharedInstance”的情况下从单例类中设置和获取(全局)值.我希望代码看起来像这样……
frameRate = Singleton.frameRate; Singleton.frameRate = 42;
为了实现这一点,我们需要存储在单例中的每个变量都有一个getter和setter类方法.然后,类方法转到实例以将数据存储在ivar中.主程序不直接访问该实例.
getter看起来像这样:
+ (int) frameRate { return [[Singleton instance] ivarFrameRate]; }
通过在此处调用实例方法,类方法将在首次使用时自动实例化对象.一旦实例化单例,实例就会按常规存储ivars.在这里,我用“ivar”作为前缀,使ivar显式化.
@property int ivarFrameRate;
和
@synthesize ivarFrameRate;
这会自动创建传统的getter(和setter)方法来访问ivar.
(编辑 – 这是一个完整的例子)
// Singleton.h #import <Foundation/Foundation.h> @interface Singleton : NSObject { float ivarFrameRate } @property float ivarFrameRate; - (id) init; + (Singleton *) instance; + (float) frameRate; + (void) setFrameRate:(float)fr; @end
和
// Singleton.m #import "Singleton.h" @implementation Singleton @synthesize ivarFrameRate; static Singleton* gInstance = NULL; + (Singleton*)instance { @synchronized(self) { if (gInstance == NULL) gInstance = [[self alloc] init]; } return(gInstance); } - (id)init { self = [super init]; return self; } + (float) frameRate { return [[Singleton instance] ivarFrameRate]; } + (void) setFrameRate:(float)fr; { [[Singleton instance] setIvarFrameRate:fr]; }