关闭

IOS中的单例模式

标签: 设计模式编程
428人阅读 评论(0) 收藏 举报
分类:
在设计模式中有一个“单例模式”,对应的我们常常会设计“单例类”(或称单件类)。但在实际应用中,我们常常也需要使用“半单例”。下面我们具体谈谈单例和半单例,以及他们的用法和区别。

单例模式

单例模式(singleton)顾名思义,就是只有一个实例

作为对象的创建模式[GOF95], 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

也就是说,对于一个单例类,不论实例化对象多少次,都只有一个对象实例,而且这个实例一定是一个全局的能被整个系统访问到。

下面是Objective-C中完整的单例类的实现:

Singleton.h

#import <Foundation/Foundation.h>


@interface Singleton : NSObject


+(id)shareInstance;


@end



Singleton.m

#import "Singleton.h"

static Singleton * instance = nil;

@implementation Singleton


+(id)shareInstance

{

    if(instance == nil)

    {

        instance = [[super allocWithZone:nil]init];  //super 调用allocWithZone            

    }

    return instance;

}


+(id)allocWithZone:(NSZone *)zone

{

    return [Singleton shareInstance];   

}


//可写可不写

- (id)init 

{

    if (instance) 

    {

        return instance;

    }

    

    self = [super init];

    return self;

}


-(id)copy

{

    return self;

}

- (id)copyWithZone:(NSZone *)zone

{

    return self;

}

-(id)retain

{

    return self;

}

- (oneway void)release 

{

    // Do nothing

}


- (id)autorelease 

{

    return self;

}


- (NSUInteger)retainCount 

{

    return NSUIntegerMax;

}

@end



解释说明:

1.static Singleton * instance = nil;

静态全局变量,始终指向实例化出的对象。

2.+(id)shareInstance;

外界初始化得到单例类对象的唯一借口,这个类方法返回的就是instance,即类的一个对象,

如果instance为空,则实例化一个对象,如果不为空,则直接返回。这样保证了实例的唯一。

3.-(id)copy;

- (id)copyWithZone:(NSZone *)zone;

这两个方法是为了防止外界拷贝造成多个实例,保证实例的唯一性。

4.-(id)retain;

因为只有一个实例对象,所以retain不能增加引用计数。

5.- (NSUInteger)retainCount;

因为只有一个实例对象,设置默认引用计数。这里是取的NSUinteger的最大值,当然也可以设置成1或其他值。

6.- (onewayvoid)release;

oneway void是用于多线程编程中,表示单向执行,不能“回滚”,即原子操作。


半单例

1.半单例不同于单例,它可以实例化多个对象。

2.在程序中系统要求能访问到这个类的当前对象实例。

比如说:我们对于一个ViewController,我们可以实例化多个。在ViewController中,我们给他添加了很多视图View。

这些View中,当与用户发生某个交互时,我们由需要向Controller发送消息,实现响应操作。那么,View必须能找到当前的ViewController。这时,我们可以将ViewController设置成一个半单例类。


以“翻书”程序为例:这里涉及到两个类LeavesViewController 和LeavesView

显然,我们是在LeavesViewController中添加多个LeavesView实现多页效果,

当判断出LeavesView翻到最后一页时,我们需要让LeavesViewController响应,跳到下一个Controller,其他场景视图。

LeavesViewController类为“半单例”:

LeavesViewController.h

#import <UIKit/UIKit.h>

#import "LeavesView.h"


@interface LeavesViewController : UIViewController <LeavesViewDataSource, LeavesViewDelegate

{

LeavesView *leavesView;

}

@property(nonatomic,retain)LeavesView *leavesView;


+ (id)shareInstance;


- (void)goToPlay;

@end


LeavesViewController.m

#import "LeavesViewController.h"

#import "ASCcLevelOnePaperScene.h"


static LeavesViewController *leavesViewInstance = nil;


@implementation LeavesViewController


@synthesize leavesView;

- (id)init 

{

    if (self = [super init]) 

    {

        leavesView = [[LeavesView alloc] initWithFrame:CGRectZero];

        leavesView.mode = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? LeavesViewModeSinglePage : LeavesViewModeFacingPages;

        leavesViewInstance = self;       //注意这里

    }

    return self;

}


- (void)dealloc 

{

    [leavesView release];

    leavesViewInstance = nil;      //释放全局变量

    [super dealloc];

}


+ (id)shareInstance

{   

    //NSAssert(leavesViewInstance!=nil,@"leavesViewInstance can not be nil!");

    if(leavesViewInstance == nil)

        leavesViewInstance = [self init];

    return leavesViewInstance;

}


这里只展示了“半单例”的实现部分,关于Controller都有的ViewDidLoad等方法和其他相关实现方法,这里与“半单例”无关,不做展示

LeavesView只是一个普通的视图类。

当LeavesView判断到最后一页时:

if([self hasNextPage]==NO)

{

    NSLog(@"最后一页!");

    [[LeavesViewController shareInstance] goToPlay];

}


[LeavesViewControllershareInstance]得到当前ViewController。再发送消息goToPlay,让ViewController响应。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:45334次
    • 积分:1172
    • 等级:
    • 排名:千里之外
    • 原创:66篇
    • 转载:25篇
    • 译文:2篇
    • 评论:2条
    文章分类
    最新评论
  • IOS绘图使用

    lecky1991: 是不是可以调整基线的位置或者设置CTLine具体显示的位置来解决呢?

  • IOS绘图使用

    Ostroff: “这里一定要是给NSAttrubuted字设置好属性,否则中文将是旋转角度。”请问我正在做一个中英文...