Featured image of post 第7回-動的に切り替えよう - Mooを使ってディスパッチャーを作ってみよう

第7回-動的に切り替えよう - Mooを使ってディスパッチャーを作ってみよう

実行時にハンドラーを動的に切り替える機能を追加します。is => 'rw'を使って、柔軟にハンドラーを差し替える方法を学びましょう。

@nqounetです。

前回は、ハンドラーを保持して処理を振り分けるDispatcherクラスを作りました。

今回は、実行時にハンドラーを動的に切り替える機能を追加します。

問題:ハンドラーを途中で変えられない

前回のDispatcherでは、has handler => (is => 'ro')としていたため、一度セットしたハンドラーは変更できませんでした。

しかし、実際のアプリケーションでは、ユーザーの操作に応じて表示を切り替えたい場面がよくあります。例えば「一覧を見ていたけど、投稿フォームを表示したい」といった場合です。

解決策:is => 'rw'で動的に変更可能にする

前シリーズの第4回で学んだis => 'rw'を思い出してください。書き込み可能な属性にすれば、実行時にハンドラーを差し替えられます。

	sequenceDiagram
    participant User as 利用側
    participant D as Dispatcher
    participant L as ListHandler
    participant F as FormHandler

    User->>D: new(handler => ListHandler)
    User->>D: run()
    D->>L: run()
    L-->>D: 投稿一覧を表示

    User->>D: set_handler(FormHandler)
    User->>D: run()
    D->>F: run()
    F-->>D: 投稿フォームを表示

set_handlerメソッドの追加

is => 'rw'に変更し、set_handlerメソッドを追加しましょう。

 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
32
33
34
35
36
37
38
39
package Handler {
    use Moo::Role;
    requires 'run';
};

package ListHandler {
    use Moo;
    with 'Handler';

    sub run {
        my ($self) = @_;
        print "投稿一覧を表示\n";
    }
};

package FormHandler {
    use Moo;
    with 'Handler';

    sub run {
        my ($self) = @_;
        print "投稿フォームを表示\n";
    }
};

package Dispatcher {
    use Moo;

    has handler => (
        is       => 'rw',      # roからrwに変更
        required => 1,
        handles  => ['run'],
    );

    sub set_handler {
        my ($self, $new_handler) = @_;
        $self->handler($new_handler);
    }
};

is => 'rw'にすることで、handler属性を後から変更できるようになりました。

$dispatcher->handler($new)で直接変更できるのに、なぜset_handlerを作るの?」と思うかもしれません。これは、コードを読む人に「ここでハンドラーを切り替えている」という意図を明確に伝えるためです。

実行時にハンドラーを差し替えるデモ

実際に動かしてみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 最初はListHandlerで起動
my $dispatcher = Dispatcher->new(handler => ListHandler->new());
$dispatcher->run();  # 投稿一覧を表示

# FormHandlerに切り替え
$dispatcher->set_handler(FormHandler->new());
$dispatcher->run();  # 投稿フォームを表示

# またListHandlerに戻す
$dispatcher->set_handler(ListHandler->new());
$dispatcher->run();  # 投稿一覧を表示

1つのDispatcherオブジェクトで、ハンドラーを自由に切り替えられるようになりました。ユーザーの操作やリクエストに応じて、動的に振る舞いを変えられます。

まとめ

  • is => 'rw'を使えば、実行時にハンドラーを切り替えられる
  • set_handlerメソッドで意図を明確にした切り替えが可能
  • 1つのDispatcherで複数のハンドラーを使い分けられる柔軟性を獲得した

次回予告

次回は、複数のハンドラーをあらかじめ登録しておく「レジストリ」の仕組みを作ります。ハンドラーを名前で管理できるようになります。

comments powered by Disqus
Hugo で構築されています。
テーマ StackJimmy によって設計されています。