« 2007年5月13日 - 2007年5月19日 | トップページ | 2007年7月1日 - 2007年7月7日 »

2007年6月20日 (水)

C言語でSingleton 2

前の記事 に続きC言語でSingletonをやってみます。
今度は使えそうな香りがするようなものになっていると思います。

今回も「Java言語で学ぶデザインパターン」が元ネタです。
簡単に言うと数字をカウントするオブジェクトをSingletonで実装するっていう課題です。

ではヘッダファイルから、
[singleton.h]

typedef struct {
    /* int ticket; */
    int (*getNextTicketNumber)();
} *Singleton;

Singleton get_instance();

前回と違いSingletonの中身が構造体 (といってもintを返す関数へのポインタだけですが) になっています。

続いてSingleton、
[singleton.c]

#include <stdlib.h>
#include "singleton.h"

static int          ticket = 1000;
static Singleton singleton;

static int inc()
{
    return ticket++;
}

Singleton get_instance()
{
    if (!singleton) {
        singleton = malloc(sizeof(*singleton));
        singleton->getNextTicketNumber = inc;
    }
    return singleton;
}

ticketとinc()がstaticなのがポイントで、これらは他のファイルから呼ぶことができません。なので、ticketを直接アクセスすることはできず、get_instance()から得られるSingleton型の変数を通してしかアクセスできなくなります。

最後にメイン、
[main.c]

#include <stdio.h>
#include "singleton.h"

int main()
{
    int i;

    for (i = 0; i < 10; i++) {
        printf("%d\n", get_instance()->getNextTicketNumber());
    }

    return 0;
}

です。get_instance()->getNextTicketNumber()みたいな表記を試しにしてみたら特に異状なく動作しました(gcc4)。

実行結果は

1000
1001
1002
1003
1004
1005
1006
1007
1008
1009

です。こうやってカプセル化を実現するのはありかと思います。

| | コメント (0) | トラックバック (0)

2007年6月17日 (日)

C言語でSingleton

Java言語で学ぶデザインパターンを参考にやってみた。

まずはヘッダファイル。
singleton.h

typedef int *Singleton;

Singleton get_instance();

Singletonという型を宣言。実際に利用するときはint *ではなくなる可能性が高い。
get_instance()でオブジェクトを取得する。

続いてsingeton自体となるファイル。
singleton.c

#include <stdlib.h>
#include "singleton.h"

static Singleton singleton;

Singleton get_instance()
{
    /* ロックする */
    if (!singleton) {
        singleton = malloc(sizeof(*singleton));
    }
    /* ロック解除 */
    return singleton;
}

singletonの宣言にstaticを付けることで、外部のファイルからアクセスできなくする。
get_instanceではそれで領域がとれていなかったらとるようにして、singletonを返す。
スレッドの事とかを考慮して、ロックを掛ける必要がでてくる事も出てくるかもしれない。

最後に利用するファイル。
main.c

#include <stdio.h>
#include "singleton.h"

int main()
{
    Singleton obj1;
    Singleton obj2;

    printf("Start.\n");
    obj1 = get_instance();
    obj2 = get_instance();
    if (obj1 == obj2) {
        printf("obj1とobj2は同じインスタンスです。\n");
    }
    else {
        printf("obj1とobj2は同じインスタンスではありません。\n");
    }
    printf("End.\n");

    return 0;
}

実行結果は

Start.
obj1とobj2は同じインスタンスです。
End.

一応意図どおりできました。
ただ、mainの方で、
Singleton s;
s = malloc(sizeof(*s));
みたいな事は防げないので、厳密にはSingletonではないのだろうな。
あとfreeしてないのも問題か

| | コメント (0) | トラックバック (0)

« 2007年5月13日 - 2007年5月19日 | トップページ | 2007年7月1日 - 2007年7月7日 »