Commandパターン
命令(Command)をメソッド呼び出しではなくて、オブジェクトとして実装するパターン。通常は命令したい内容に応じてメソッド引数を変えるが、Commandパターンはオブジェクトを渡す。
メリット
- 命令そのものに情報を持たせることができる
- 複数の命令を呼び出し側が組み合わせできる
- 命令の集合をつくることができる
使用例
- アプリケーションのredo/undo(実行したオブジェクトを保持)
- 総実行時間の予測(各Commandオブジェクトが予測時間を持つ)
- 非同期キュー処理(Commandオブジェクトを一旦保存して、リモート/別プロセス実行)
簡単な実装
足し算と引き算をCommandパターンで実装してみる(実にくだらないけど)
- Commandクラス
package Command; sub new { my ($class, $ref_hash) = @_; return bless({ calc => $ref_hash }, $class); } sub execute { die; } 1;
- Command::Plusクラス
package Command::Plus; use base qw(Command); sub execute { my ($self, $val) = @_; $self->{calc}{value} += $val; push(@{$self->{calc}{exec_log}}, "add val($val)."); } 1;
- Command::Minusクラス
package Command::Minus; use base qw(Command); sub execute { my ($self, $val) = @_; $self->{calc}{value} -= $val; push(@{$self->{calc}{exec_log}}, "minus val($val)."); } 1;
- mainプログラム
use Command; use Command::Plus; use Command::Minus; my %calc = ( value => 0, exec_log => [], ); my $plus = new Command::Plus(\%calc); my $minus = new Command::Minus(\%calc); $plus->execute(1); # 1 $plus->execute(4); # 5 $minus->execute(2); # 3 printf("value is %d\n", $calc{value}); printf("%s\n", join("\n", @{$calc{exec_log}}));
- 結果
value is 3 add val(1). add val(4). minus val(2).
まとめ
- Commandパターンはメソッド呼び出しに比べて、実装は手間。
- ただ、履歴を残す/命令の集合をつくれる等、再利用性がぐっと高まることが大きなメリット。