Entry

プログラミングメモ - Movable Type の Singleton 実装

2008年06月14日

巷は MT4 だってのに,いまだに MT 3.2-ja-2 を愛用しています。で,今このソースを読んでいます。以前もぼちぼち読んでたんですけど,まとめて読みたいと思ったもんで,ちょっとメモ。

Singleton パターンってのは,そのクラスのオブジェクト(インスタンス)がひとつしか作られないことが保証されているパターンのこと。GOF のデザインパターンの中でも有名なもののひとつなので,知っている方も多いと思います。アプリケーション全体を設定するときだとか,特定のオブジェクトにアクセスするためのチケット代わりに使われることが多いみたい(このオブジェクトを使う場合はこの Singleton を持っててくださいね,みたいに使う)。

ここでは,ユーザのリクエスト(HTTP リクエスト)に対する,アプリケーションの設定情報やキャッシュ情報を Singleton で生成できるようにしています。MT::Request より。

package MT::Request;
use strict;

use MT::ErrorHandler;
@MT::Request::ISA = qw( MT::ErrorHandler );

use vars qw( $r );
sub instance {
    return $r if $r;
    $r = __PACKAGE__->new;
}

sub finish { undef $r }

sub reset { $r->{__stash} = {} if $r }

sub new {
    my $req = bless { __stash => { } }, $_[0];
    $req;
}

sub stash {
    my $req = shift;
    my $key = shift;
    $req->{__stash}->{$key} = shift if @_;
    $req->{__stash}->{$key};
}
*cache = \&stash;

1;
__END__

本当に簡単な実装ですね。Singleton としてはあまり厳密ではないんですけど,要するに,reset() で内部状態をリセットしてから,instance() メソッドでインスタンスを受け取るようになっています。instance() メソッドは,インスタンスである $r がある場合は,それを返し,まだ作られていない場合は,新しく作って返します。最後は finish() でお片づけです。

呼び元は例えばこんな感じ。MT::App より。

    ## Initialize the MT::Request singleton for this particular request.
    $app->request->reset();
    $app->request('App-Class', ref $app);
    $_->init_request($app) foreach @MT::Plugins;

そして使ってるとこ。MT::Util より。

    unless ($cache) {
        MT::Request->instance->cache('formats', $cache = {});
    }

Singleton パターンは,マルチスレッド環境なんかでは特に重要で,きっちり同期を取る必要があるんですけど,MT のようなアプリケーションの場合,リクエスト単位でスレッドが生成されてからは,それっきりなことが普通なので,あまり厳密に実装はしていないようです(同期のコストもバカになりませんしね)。むしろ,グローバル変数として利用したいデータを,あちこちから参照できるようにする仕組みといったところのようです。

なんだか近頃 C ばっかいぢってるので,LL なコードを見るとほっとします。こゆコードリーディングも精神衛生的にいいですね。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN