PerlでMediator

PerlでMediator


ホークスを
出てから打つのが
ペーニャです

どーも、みんなのアイドルやまぴもです。
今日はPerlでMediator。
Mediatorの活用としては多くのオブジェクトが相互に作用して動く場合に、
Mediator(ディレクター)クラスを準備して、ユーザーはそのクラスに対して
オペレーションをすることでユーザーから複数のオブジェクトの相互作用を
意識させないようなパターンです。
GoF本の例だとダイアログウィンドウの中にチェックボックスやらテキストボックスが
あって例えば、チャックボックスにチェックを入れたらテキストボックスがアクティブになる
といったような制御をディレクターがよろしくやってくれますよという感じですかね。

この場合の動きとしてはチェックボックスに何らかの変化があった場合に、
チェックボックスが自身の挙動が変わったことをディレクターに通知して、
その通知を元にディレクターがテキストボックスをアクティブにするといった具合です。

ソースはこのへんに
GitHub ka-yamashita

今回のコード構成は

・Main.pl
ユーザー操作コードです
・Mediator.pm
Medietorの記述
・Parts.pm
Mediatorを介して操作したいパーツの記述

と言った感じです。
Partsから見て行きましょう。

[Perl]
use utf8;
#——————————————-
# Name:Parts.pm
#——————————————-
#パーツの抽象クラス
package Parts;

use Mediator;
use Moose::Role;
#ディレクターの参照変数
has ‘director’ => (
is => ‘rw’,
isa => ‘Mediator’,
required => ‘1’
);
#自身の名前格納変数
has ‘name’ => (
is => ‘rw’,
isa => ‘Str’,
);
#自身の値格納変数
has ‘value’ => (
is => ‘rw’
);
no Moose::Role;

#オブジェクトの値が変わった際にディレクターに通知するメソッド
sub change {
my $self = shift;
$self->director->parts_change($self);
};
#値の設定
sub setvalue {
my $self = shift;
$self->value(shift);
$self->change();
}
#文字列を扱うクラス
package Parts::Parts_String;
use Moose;
with ‘Parts’;
has ‘+value’ => (
isa => ‘Str’
);
__PACKAGE__->meta->make_immutable();
no Moose;

#数値を扱うクラス
package Parts::Parts_Int;
use Moose;
with ‘Parts’;
has ‘+value’ => (
isa => ‘Int’
);
__PACKAGE__->meta->make_immutable();
no Moose;
1;
[/Perl]

まずParts_Str,Parts_Intと言うのは各々value(オーバーライド)変数に文字列、数値を保持するだけの
クラスです。
継承している変数としてdirectorがあり、ここに自分の会話の相手となるディレクターの参照変数を
持ちます。
例えばset_valueメソッドが呼ばれた場合、自身のvalueを書き換え、その後
changeメソッドを呼び出し、directorに自身の値が変わったことを通知するのです。

[Perl]
$self->director->parts_change($self);
[/Perl]

この部分でディレクターのperts_changeメソッドに自身の参照を渡して、
自身の値が変わったことを通知するわけですね。
#重ね書き失礼

その通知を受け取ったディレクターが何をするかというと、

[Perl]
use utf8;
#———————————————-
# Name:Mediator.pm
#———————————————-

# Mediaterの抽象クラス
package Mediator;
use Moose::Role;
requires ‘parts_change’;
no Moose::Role;

# Mediaterの具象クラス
package Parts_Director;
use Parts;
use Moose;
with ‘Mediator’;

#パーツ格納用変数
has ‘parts_int’ => (
is => ‘rw’,
isa => ‘Parts’
);
has ‘parts_str’ => (
is => ‘rw’,
isa => ‘Parts’
);
__PACKAGE__->meta->make_immutable();
no Moose;

#パーツの作成
#テストコード実行のため便宜上実装
sub create_parts {
my $self = shift;
$self->parts_str(Parts::Parts_String->new(director=>$self,name => ‘strman’,value => ‘test’)) unless $self->parts_str;
$self->parts_int(Parts::Parts_Int->new(director=>$self,name => ‘intman’,value => ‘123’)) unless $self->parts_int;
}

#パーツのセッター
#テストコード実行のため便宜上実装
sub set_parts_value {
my ($self,$value) = @_;
if($value =~ /[^0-9]/){
$self->parts_str->setvalue($value);
}else{
$self->parts_int->setvalue($value);
}
}

#パーツの値が変わった際に子オブジェクトから呼び出されるメソッド
sub parts_change {
my ($self,$parts)=@_;
print $parts->name(),”の値が変更されました。\n”;
print “気になる値は、”,$parts->value,”です\n”;
};
1;
[/Perl]

parts_changeメソッドで、変更されたパーツの名前と、その値を表示するわけです。
実際の使い方としては

[Perl]
use utf8;
binmode(STDOUT, “:utf8”);
#——————————————-
# Name:Main.pl
#——————————————-
use Mediator;
use Parts;

#ディレクターのインスタンス化
my $m=Parts_Director->new();

#自身のディレクションするパーツを作成する
$m->create_parts();

#数値の値を変える
$m->set_parts_value(1);

#文字の値を変える
$m->set_parts_value(abc);

[/Perl]

実行するとこんな感じ。

[Shell]
[Mediator]$perl Main.pl
intmanの値が変更されました。
気になる値は、1です
strmanの値が変更されました。
気になる値は、abcです
[Mediator]$
[/Shell]

さて、最近デザインパターンばっかりで飽きてきつつあるので
あとCommandとFecade書いたら次のステップに進みたいと思います。
それでは!

コメントは受け付けていません。