Objective-C 设计模式之单

本文详细介绍了Objective-C中的单例模式实现方法,包括如何通过工厂方法返回唯一实例,以及如何确保实例不被释放,同时展示了单例模式在实际应用中的效果。

http://unmi.cc/objective-c-dp-singleton

Objective-C 设计模式之单例

作为设计模式中最简单的一个,单例模式还是在很多系统中都会用到,总有那么一些实例,从始至终只需要它的一个实例,而且任何时候都要总方便的得到,像 Application 对象啦,环境对像啊。

要保持你设计的类别人只会初始出一个实例来,像 Java/C++/C# 中的做法一般希望能保证以下那些:

1. 构造方法藏起来,private 修饰,这样只能通过统一的工厂方法获得实例,因为 new 出来的总是新对象
2. 克隆方法出来的对象仍然是原来的对象
3. 反序列化出的对象也仍然是原来那个唯一的对象(这好像有点难)
4. 一般程序运行期间,该单实例不被释放
5. 一般要求工厂方法是原子性的,也是避免返回了不同的实例
6. 等等................. 是否还有些补充?

不一定每一点都真正考虑到,因为不是每个使用都都那么变态或不存在某些使用场景。

而我们这里的 Objective-C 有其语言的较大特殊性,是通过 alloc 来创建实例的,无法把构造方法 alloc 隐藏起来,但我们总是有办法的,可以做到:

1. 工厂方法返回唯一的实例
2. 多次调用 alloc 构造出的实例与 工厂方法得到的是同一个
3. 让你释放不掉这个实例,引用计数不让归零现在来看看 Objective-C 中的单例模式的代码实现吧:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//singleton.h
 
#import <Foundation/Foundation.h>
 
@interface Singleton : NSObject
{
 
}
 
+ (Singleton *) sharedInstance;
 
- (void) operation;
 
@end
 
//singleton.m
#import "Singleton.h"
 
@implementation Singleton
 
static Singleton *_sharedInstance = nil;
 
- (void) operation
{
  // do something
  NSLog(@"Singleton");
}
 
+ (Singleton *) sharedInstance
{
  if (_sharedInstance == nil)
  {
    _sharedInstance = [NSAllocateObject([self class], 0, NULL) init];
  }
  
  return _sharedInstance;
}
 
+ (id) allocWithZone:(NSZone *)zone
{
  return [[self sharedInstance] retain];
}
 
- (id) copyWithZone:(NSZone*)zone
{
  return self;
}
 
- (id) retain
{
  return self;
}
 
- (NSUInteger) retainCount
{
  return NSUIntegerMax; // denotes an object that cannot be released
}
 
- (oneway void) release
{
  // do nothing
}
 
- (id) autorelease
{
  return self;
}
 
@end

马上来看看效果,用下面的代码来分别得到 Singleton 的三个实例,s1, s2, s3:

1
2
3
4
5
    Singleton *s1 = [Singleton alloc];
    Singleton *s2 = [Singleton sharedInstance];
    Singleton *s3 = [Singleton alloc];
     
    NSLog(@"s1:%@, s2%@, s3%@", s1, s2, s3);

执行后打印出来的三个实例的地址是一样的:

s1:<Singleton: 0x100114890>, s2<Singleton: 0x100114890>, s3<Singleton: 0x100114890>

说明它们是同一个实例,无论是 alloc 还是 sharedInstance,好了现在对照着成功的案例可以放心的解释一下了:

1. 每一次 alloc 都得经过 allocWithZone: 方法,然后进到 sharedInstance 方法,这就统一了入口
2. release/autorelease/retainCount 方法保证了实例不被释放
3. copyWithZone: 和 retain 用以确保克隆还是保留的仍然是原来那个唯一的实例

再有更苛刻的条件就暂不考虑了,比如应该可以加上 @synchronized 来原子性一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值