ios-设计模式-单例

转载请出名出处:http://my.oschina.net/liuchuanfeng/blog/660917 
设计模式

如下为翻译部分:安全

翻译自:http://www.galloway.me.uk/tutorials/singleton-classes/  如有不精确之处,还望不吝赐教。函数

单例模式singleton pattern是常常使用的设计模式,它不用传递参数,就能在两个不一样的代码块之间实现数据共享测试

好比:从任何地方调用UIApplication 的 sharedApplication方法,都会返回与当前运行程序相关的UIApplication实例。atom

如何实现单例类:(ARC)spa

#import <foundation/Foundation.h>

@interface MyManager : NSObject {    
    NSString *someProperty;
}

@property (nonatomic, retain) NSString *someProperty;

+ (id)sharedManager;

@end
#import "MyManager.h"
@implementation MyManager
@synthesize someProperty;
#pragma mark Singleton Methods
+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedMyManager = [[self alloc] init];
    });
    return sharedMyManager;
}
- (id)init {
  if (self = [super init]) {
      someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
  }
  return self;
}
- (void)dealloc {
  // Should never be called, but just here for clarity really.
}
@end

上面定义了静态变量sharedMyManager 在sharedManager里只被实例化一次,GCD的dispatch_once方法保证只被建立一次,而且是线程安全的。.net

固然,若是不想使用GCD,可使用下面的代码:线程

+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    @synchronized(self) {
        if (sharedMyManager == nil)
            sharedMyManager = [[self alloc] init];
    }
    return sharedMyManager;
}

用下面的方法能够从任何一个地方调用这个单例
翻译

MyManager *sharedManager = [MyManager sharedManager];

单例使用普遍,好比处理CoreLocation or CoreData函数设计

非ARC代码:

#import "MyManager.h"
static MyManager *sharedMyManager = nil;
@implementation MyManager
@synthesize someProperty;
#pragma mark Singleton Methods
+ (id)sharedManager {
  @synchronized(self) {
      if(sharedMyManager == nil)
          sharedMyManager = [[super allocWithZone:NULL] init];
  }
  return sharedMyManager;
}
+ (id)allocWithZone:(NSZone *)zone {
  return [[self sharedManager] retain];
}
- (id)copyWithZone:(NSZone *)zone {
  return self;
}
- (id)retain {
  return self;
}
- (unsigned)retainCount {
  return UINT_MAX; //denotes an object that cannot be released
}
- (oneway void)release {
  // never release
}
- (id)autorelease {
  return self;
}
- (id)init {
  if (self = [super init]) {
      someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
  }
  return self;
}
- (void)dealloc {
  // Should never be called, but just here for clarity really.
  [someProperty release];
  [super dealloc];
}
@end


如下加入个人理解:

不知你是否在上面ARC下用以下代码测试过

    MyManager *mm1 = [[MyManager alloc] init];
    MyManager *mm2 = [[MyManager alloc] init];
    MyManager *mm3 = [[MyManager alloc] init];
    NSLog(@"\n%@\n%@\n%@",mm1,mm2,mm3);
    
    MyManager *mm4 = [MyManager sharedManager];
    MyManager *mm5 = [MyManager sharedManager];
    NSLog(@"\n%@\n%@",mm4,mm5);

mm1 mm2 mm3的值(地址)是不同的,mm4 mm5同样,重写allocWithZone就能保证mm1 mm2 mm3的值同样了。固然若是须要copy,则要重写copyWithZone

+(id)allocWithZone:(NSZone *)zone{
    @synchronized(self){
        if (sharedMyManager == nil) {
            sharedMyManager = [super allocWithZone:zone]; //确保使用同一块内存地址
            return sharedMyManager;
        }
        return sharedMyManager;
    }
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

为何实现allocWithZone、copyWithZone这两个方法?

建立对象的时候,alloc表示申请内存,init表示初始化,程序在alloc时,会在allocWithZone这个方法申请内存,咱们只要在这个方法中调用sharedManager返回单例便可。这样就不会申请屡次内存了。拷贝对象以此类推,同理所得,要重写copyWithZone。这样就保证了这个类只被实例化了一次。


@synchronized 保证线程安全

单例能够用来传值,系统UIApplication NSUserDefaults 就是单例类。

单例模式确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例

相关文章
相关标签/搜索