@nqounetです。
前回は、複数のハンドラーを登録して管理するレジストリを作りました。
今回は、アクション名から自動でハンドラーを選択・生成する仕組みを作ります。
問題:ハンドラーを事前に全部登録するのは面倒
前回のレジストリでは、使うハンドラーを事前にすべて登録しておく必要がありました。
1
2
3
4
| $dispatcher->register_handler('list', ListHandler->new);
$dispatcher->register_handler('form', FormHandler->new);
$dispatcher->register_handler('thread', ThreadHandler->new);
# まだまだ続く...
|
ハンドラーが10個、20個と増えてくると、登録コードも長くなってしまいます。もっと楽な方法はないでしょうか?
解決策:名前からハンドラーを自動生成する
アクション名から対応するハンドラークラスを特定し、必要なときに生成する仕組みを作ります。これは「Factory(ファクトリー)」と呼ばれるパターンの簡易版です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| package Dispatcher {
use Moo;
use Module::Load qw(load);
has handler_namespace => (
is => 'ro',
default => sub { 'Handler' },
);
sub handler_for {
my ($self, $action) = @_;
# 'list' → 'Handler::List' のように変換
my $class = $self->handler_namespace . '::' . ucfirst($action);
# クラスを読み込み
eval { load $class };
if ($@) {
die "Handler not found: $class";
}
# オブジェクトを生成して返す
return $class->new;
}
sub dispatch {
my ($self, $action) = @_;
my $handler = $self->handler_for($action);
$handler->run;
}
};
|
handler_forメソッドは、アクション名から対応するクラス名を組み立て、そのクラスを読み込んでオブジェクトを生成します。
使ってみよう
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # ハンドラークラスを用意
# Handler/List.pm
package Handler::List {
use Moo;
with 'Handler';
sub run { print "投稿一覧を表示\n" }
};
# Handler/Form.pm
package Handler::Form {
use Moo;
with 'Handler';
sub run { print "投稿フォームを表示\n" }
};
# ディスパッチャーを使う
my $dispatcher = Dispatcher->new;
# 名前を指定するだけで自動的にハンドラーが生成される
$dispatcher->dispatch('list'); # Handler::List が自動で生成・実行される
$dispatcher->dispatch('form'); # Handler::Form が自動で生成・実行される
|
事前登録なしで、名前を指定するだけでハンドラーが使えるようになりました。
flowchart TD
A["dispatch('list')"] --> B["handler_for('list')"]
B --> C["クラス名を生成: Handler::List"]
C --> D["クラスを読み込み"]
D --> E["new でオブジェクト生成"]
E --> F["handler->run 実行"]
まとめ
- 名前からハンドラーを自動生成する仕組みをFactoryパターンと呼ぶ
- アクション名からクラス名を組み立てて動的に読み込む
Module::Loadのload関数でクラスを動的に読み込める- 事前登録なしで、必要なときにハンドラーを生成できる
次回予告
次回は、URLパターンでハンドラーを振り分ける機能を追加します。より実践的なルーティングの仕組みを学びましょう。お楽しみに。