en

hi, it seems you are using microsoft internet explorer. it doesn't match web standard and causes problems browsing this site. please please please use mozilla firefox or google chrome instead. thank you!

zh

哦哦!您正在使用Internet Explorer 瀏覽器,它與我們的網頁標準並不相容,可能會導致畫面顯示不正常。
請改用 Mozilla Firefox 或者 Google Chrome 才能正常瀏覽本網站,謝謝!

9.26.2011

製作 Singleton 單一物件的方法

Singleton 可以把它想成是一個全域物件,就如同全域變數一般,在整個程式中只會有單一一個這樣的物件,這類的技巧很常在撰寫遊戲程式時被使用,除了可以減少記憶體資源的過度浪費外,也可以減少許多參數在傳遞上的困擾,下列程式碼就示範如何製作出一個 Singleton 物件,與它的使用方式。

在製作出 Singleton 物件方面,我們賦予這個物件一個 count 值,並提供兩個實體方法,用來疊加和呈現這個 count 值。新增一個 NSObject 的 Subclass 並命名為 SingletonObject,以下是此物件內部的完整程式碼。

SingletonObject.h
#import <Foundation/Foundation.h>

@interface SingletonObject : NSObject {
@private
    int count;
}

//統一透過此函式來調用SingletonObject的方法
+ (SingletonObject *)sharedSingletonObject;

//疊加
- (void)addCount;

//呈現
- (void)showCount;
@end

SingletonObject.m
#import "SingletonObject.h"

@implementation SingletonObject

//宣告一個靜態的SingletonObject物件
static SingletonObject *_singletonObject = nil;

- (id)init {
    self = [super init];
    if (self) {

        //將COUNT初始化為0
        count = 0;
    }

    return self;
}

//執行時會判斷是否_singletonObject已經完成記憶體配置
+ (SingletonObject *)sharedSingletonObject {

    @synchronized([SingletonObject class]) {

        //判斷_singletonObject是否完成記憶體配置
            if (!_singletonObject)
                [[self alloc] init];

            return _singletonObject;
        }

    return nil;
}

+ (id)alloc {
    @synchronized([SingletonObject class]) {

        //避免 [SingletonObject alloc] 方法被濫用
        NSAssert(_singletonObject == nil, @"_singletonObject 已經做過記憶體配置");
        _singletonObject = [super alloc];

        return _singletonObject;
    }

    return nil;
}

- (void)addCount {
    count += 1;
}

- (void)showCount {
    NSLog(@"%d", count);
}

- (void)dealloc {
    [super dealloc];
}

@end

在上述程式碼中有使用到 NSAssert 指令,它可以用來避免 [SingletonObject alloc] 方法遭到濫用,因而製作出第二個 SingletonObject 的 instance,這就違背了當初我們建立 SingletonObject 的初衷。

此物件在使用上也非常簡單,只要使用下列程式碼便可以操作 SingletonObject 中的方法。

[[SingletonObject sharedSingletonObject] addCount];
[[SingletonObject sharedSingletonObject] showCount];

至於要如何證明 SingletonObject 在程式中只存在單一一個呢?首先,我們建立一個新的物件並在它程式初始化的地方將  count 值疊加三次,程式瑪如下。

OtherObject.m
#import "OtherObject.h"
#import "SingletonObject.h"

@implementation OtherObject

- (id)init {
    self = [super init];
    if (self) {

        [[SingletonObject sharedSingletonObject] addCount];
        [[SingletonObject sharedSingletonObject] addCount];
        [[SingletonObject sharedSingletonObject] addCount];
    }

    return self;
}

- (void)dealloc {
    [super dealloc];
}

@end

接著,回到主要程式碼比較一下在宣告此物件之前與之後的 count 值,如果兩個數值一樣,那麼表示在宣告 OtherObject 時所曡加的其實是另一個 SingletonObject 的 instance,若是兩者的數值差距為 3,則表示我們已經成功製作出一個 Singleton 單一(全域)物件,其程式瑪如下。

#import <Foundation/Foundation.h>
#import "SingletonObject.h"
#import "OtherObject.h"

int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    [[SingletonObject sharedSingletonObject] showCount];

    //宣告一個OtherObject物件
    OtherObject *theObject = [[OtherObject alloc]init];
    [theObject release];

    [[SingletonObject sharedSingletonObject] showCount];

    [pool drain];
    return 0;
}







2 則留言:

  1. 匿名3/21/2013

    請問Singleton 這個Object該如何去release呢?
    謝謝

    回覆刪除