Decorator

理解の足らない部分が見えてきたけれど、兎に角23パターン全部やってみる。

use strict;
use warnings;

{
    package Display;
    use strict;
    use warnings;
    sub getColumns {die;}
    sub getRows {die;}
    sub getRowText {die;}
    sub show {
        my ($self, ) = @_;
        for(my $i=0; $i<$self->getRows(); $i++){
            print $self->getRowText($i),"\n";
        }
    }
}

{
    package StringDisplay;
    use strict;
    use warnings;
    our @ISA = qw/Display/;
    sub new {
        my ($class, $string) = @_;
        my $self = {
            string => $string,
        };
        return bless $self, $class;
    }
    sub getColumns {
        return length($_[0]->{string});
    }
    sub getRows {
        return 1;
    }
    sub getRowText {
        my ($self, $row) = @_;
        if($row == 0){
            return $self->{string};
        } else {
            return '';
        }
    }
}

{
    package Border;
    use strict;
    use warnings;
    our @ISA = qw/Display/;
}
{
    package SideBorder;
    use strict;
    use warnings;
    our @ISA = qw/Border/;
    sub new {
        my ($class, $display, $char) = @_;
        my $self = {
            display => $display,
            borderChar => $char,
        };
        return bless $self, $class;
    }
    sub getColumns { $_[0]->{display}->getColumns() + 2; }
    sub getRows {$_[0]->{display}->getRows();}
    sub getRowText{
        my ($self, $row) = @_;
        return $self->{borderChar}.$self->{display}->getRowText($row).$self->{borderChar};
    }
}
{
    package FullBorder;
    use strict;
    use warnings;
    our @ISA = qw/Border/;
    sub new {
        my ($class, $display) = @_;
        my $self = {
            display => $display,
        };
        return bless $self, $class;
    }
    sub getColumns { $_[0]->{display}->getColumns() + 2; }
    sub getRows { $_[0]->{display}->getRows() + 2; }
    sub getRowText {
        my ($self, $row) = @_;
        if($row == 0){
            return "+".$self->makeLine('-', $self->{display}->getColumns())."+";
        }
        elsif($row == $self->{display}->getRows() + 1){
            return "+".$self->makeLine('-', $self->{display}->getColumns())."+";
        }
        else {
            return "|".$self->{display}->getRowText($row-1)."|";
        }
    }
    sub makeLine {
        my ($self, $char, $count) = @_;
        my $buffer = '';
        $buffer .= $char for(1..$count);
        return $buffer;
    }
}

use Data::Dumper;
my $obj = StringDisplay->new('hogemoge');
my $obj2 = SideBorder->new($obj, '#');
my $obj3 = FullBorder->new($obj2);
my $obj4 = FullBorder->new(
               SideBorder->new(
                    SideBorder->new(
                        FullBorder->new(
                            StringDisplay->new('yorosiku-uho')
                                        ), "&"
                                    ), '!'
                               )
                           );


$obj->show();
$obj2->show();
$obj3->show();
$obj4->show();