Template Method

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

perlMooseデザインパターンの勉強として、こちらの本の第三章「Template Method」に載っているサンプルプログラムをperlMooseで書いてみた。

AbstractDisplayクラス

package AbstractDisplay;
use Moose::Role;
requires qw/open print close/;

sub display {
    my $self = shift;
    $self->open;
    for (1 .. 5) {
	$self->print;
    }
    $self->close;
}

AbstractDisplayクラスは、displayメソッドで、open,print,closeのそれぞれのメソッドの呼び出し方を定義している。open,print,closeメソッドの定義については、継承先に任せている。
Mooseで抽象クラスを作るには、

use Moose::Role;

と書き、packageを定義する。
抽象メソッドを指定するには、

requires qw/open print close/;

と書く。これにより、継承先ではopen,print,closeメソッドを定義するように強制できる。定義しないとコンパイルエラーになる。

CharDisplayクラスとStringDisplayクラス

AstractDisplayクラスを継承して、それぞれ違う動作をするCharDisplayクラスとStringDisplayクラスを定義する。まずはCharDisplayクラス。

package CharDisplay;
use Moose;
with 'AbstractDisplay';

has ch => (
    is => 'rw',
    isa => 'Str',
    required => 1,
    );

sub open {
    print "<<";
}

sub print {
    my $self = shift;
    print $self->ch;
}

sub close {
    print ">>\n";
}


package main;

my $o_char = CharDisplay->new(ch => "t");
$o_char->display;

実行結果がこちら。

<>

AbstractDisplayクラスの継承は、

with 'AbstractDisplay';

という記述で行なう。
charDisplayクラスでは、ch属性をhasで定義している。

has ch => (
   is => 'rw', # この属性は読み書き機能
   isa => 'Str', # この属性に設定できる型はStr(文字列)だけである
   required => 1, # オブジェクト生成時に値をセットする必要がある
);

これは「アトリビュート(属性)コンストラクタ」と呼ばれ、属性について制限がかけられる。ここでは「required => 1」に指定されているので、オブジェクト生成時に

my $o_char = CharDisplay->new( ch => 't' );

と行った感じで、ch属性の値をセットしている。

次にStringDisplayクラスの実装。

package StringDisplay;
use Moose;
with 'AbstractDisplay';

has string => (
    is => 'rw',
    isa => 'Str',
    required => 1,
    );

sub open {
    my $self = shift;
    $self->printLine();
}

sub print {
    my $self = shift;
    print '|' . $self->string . '|' . "\n";
}

sub close {
    my $self = shift;
    $self->printLine();
}

sub printLine {
    my $self = shift;
    
    my $width = length $self->string;

    print '+';
    for (1 .. $width) {
	print '-';
    }
    print "+\n";
}

package main;

my $o_string = StringDisplay->new(string => "hato test");
$o_string->display;

実行結果は、

                    • +
hato test
hato test
hato test
hato test
hato test
                    • +

以上。

デザインパターンを実装すると、なんか気持ちいいな。

参考文献