Template Method

Rubyによるデザインパターン

Rubyによるデザインパターン

を買った。

この本は、第 I 部、第 II 部、第 III 部と言う構成になっていて、第 I 部では Ruby という言語について弾丸ツアー(と本に書いてある)で紹介している。
これが第 II 部以降にあるデザインパターンの解説の前に Ruby についてのおさらいとなって、それ以降の内容がとても読みすすめやすくていいなと思った。

第 II 部に読み進めたところで、そこに Ruby で書かれているデザインパターンのコードを理解するために Perl で書き直してみようかなと思った。

本の順番にまず Template Method を Perl で表現してみることにした。

コードを書き直してみて Template Method というのは要するに抽象基底クラスでメソッド群を正にテンプレートのように定義して、各具象クラスでそれらのメソッドをオーバーライドして、おのおのの種類にあった処理を行うというもの、というように理解した。

というわけで以下コード。



抽象基底クラス Report.pm

package Report;

use warnings;
use strict;

sub new {

    my ($class) = @_;
    my $self;

    $self->{title} = '月次報告';
    $self->{text}  = [
        '順調',
        '最高の調子',
        ];

    return bless($self, $class);

}

sub output_report {

    my ($self) = @_;

    $self->output_start;
    $self->output_head;
    $self->output_body_start;
    $self->output_body;
    $self->output_body_end;
    $self->output_end;

}

sub output_body {

    my ($self) = @_;
    my $title = $self->{text};

    foreach my $line (@$title){
        $self->output_line($line);
    };

}

sub output_start {

    my ($self) = @_;

}

sub output_head {

    my ($self) = @_;

    $self->output_line($self->{title});

}

sub output_body_start {

    my ($self) = @_;

}

sub output_line {

    my ($self, $line) = @_;

    warn('Called abstract method: output_line');

}

sub output_body_end {

    my ($self) = @_;

}

sub output_end {

    my ($self) = @_;

}

1;


具象クラス HTMLReport.pm

package Report::HTMLReport;

use warnings;
use strict;

use base 'Report';

sub output_start {

    my ($self) = @_;

    print ('<HTML>');

}

sub output_head {

    my ($self) = @_;

    print ('<HEAD>');
    print ('<TITLE>'.$self->{title}.'</TITLE>');
    print ('</HEAD>');

}

sub output_body_start {

    my ($self) = @_;

    print ('<BODY>');

}

sub output_line {

    my ($self, $line) = @_;

    print ('<p>'.$line.'</p>');

}

sub output_body_end {

    my ($self) = @_;

    print ('</BODY>');

}

sub output_end {

    my ($self) = @_;

    print ('</HTML>');

}

1;


具象クラス PlainTextReport.pm

package Report::PlainTextReport;

use warnings;
use strict;

use base 'Report';

sub output_head {

    my ($self) = @_;

    print ('**** '.$self->{title}." ****\n");

}

sub output_line {

    my ($self, $line) = @_;

    print ($line);

}

1;


使用例

#!/usr/bin/perl

use Report::HTMLReport;
use Report::PlainTextReport;

my $report;

$report = Report::HTMLReport->new;
$report->output_report;

$report = Report::PlainTextReport->new;
$report->output_report;


これ以降のパターンも、気が向いたら書き直してみようかなとおもった。