2008-05-03

Objective-Cの手習い:Singletonパターン

今回は『Java言語で学ぶデザインパターン入門』からSingltonパターン。

至って簡単なプログラムだが、Objective-Cでの注意点は3つ。

  1. クラス変数がないこと
  2. メソッドの可視性を設定できないこと
  3. 決まった形式でのコンストラクタのようなものがないこと

Javaなどではクラス変数にSingletonインスタンスを納めておくのが通常だが、Objective-Cではスタティック変数を用意して格納しておくことにする。@implementaion部の最初に以下のように宣言する。

static Singleton* s_singleton = nil;

また、2と3の問題からJavaのようにコンストラクタをプライベートにして生成を制御するということができない。

で、NSObjectから継承された新たにインスタンスを作成しそうな基本メソッドをまずオーバーライドしていく。具体的にはallocWithZone/copyWithZoneなどがそれにあたる。また解放に関する部分も勝手に解放されてはまずいので手を入れておく(retain/retainCount/release/autoreleaseなど)。

具体的にはSingletonクラスの基本メソッドのオーバーライド部分は以下のようになる。

+(id)allocWithZone:(NSZone*)zone
{
    @synchronized(self) {
        if(!s_singleton) {
            s_singleton = [super allocWithZone:zone];
        }
    }
    //アップルのガイドでは最初はインスタンスを返し以降はnilを返すことに
    //なっているが、それだとうまくいかないので以下のように常にインスタンス
    //を返すように変更
    return s_singleton; 
}

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

-(id)retain
{
    return self;
}
-(unsigned)retainCount;
{
    //解放できないオブジェクトであることを示す
    return UINT_MAX; 
}
-(void)release
{
    return;
}

-(id)autorelease
{
    return self;
}

で肝心のインスタンスを提供するメソッドは以下のようになる。

+(id)getInstance
{
    @synchronized(self) {
        if(!s_singleton) {
            s_singleton = [[self alloc] init];
            printf("インスタンスを生成しました。\n");
        }
    }
    return s_singleton;
}

@synchronizedを入れているのはマルチスレッドへの考慮だ。

実はこの辺りの解説はアップルが提供するデザインガイド「Cocoa Fundamentals Guide」に「シングルトンインスタンスの作成」という解説があり、コードのサンプルも掲載され詳しく説明されている。今回はほとんどその受け売り。

SingletonSample.zip

0 件のコメント:

コメントを投稿