Bridgeパターン

use strict;
use warnings;

{
    package Display;
    use strict;
    use warnings;
    sub new {
	my ($class, $impl, ) = @_;
	my $self = {
	    impl => $impl,
	};
	return bless $self, $class;
    }
    sub open { $_[0]->{impl}->rawOpen(); }
    sub print { $_[0]->{impl}->rawPrint(); }
    sub close { $_[0]->{impl}->rawClose(); }
    sub display {
	$_[0]->open();
	$_[0]->print();
	$_[0]->close();
    }
}
{
    package StringDisplayImpl;
    use strict;
    use warnings;
    use Encode;
    our @ISA = qw/DisplayImpl/;
    sub new {
	my ($class, $string, ) = @_;
	my $self = {
	    string => $string,
	    width  => length(decode('UTF-8', $string)),
	};
	return bless $self, $class;
    }
    sub rawOpen { $_[0]->printLine(); }
    sub rawPrint { print "|".$_[0]->{string}."|\n"; }
    sub rawClose { $_[0]->printLine(); }
    sub printLine {
	print "+";
	print "-" for(1..$_[0]->{width});
	print "+\n";
    }
}
{
    package CountDisplay;
    use strict;
    use warnings;
    our @ISA = qw/Display/;
    sub new {
	my ($class, $impl) = @_;
	return $class->SUPER::new($impl);
    }
    sub multiDisplay {
	my ($self, $count) = @_;
	$self->open();
	$self->print() for(1..$count);
	$self->close();
    }
}
{
    package DisplayImpl;
    use strict;
    use warnings;
    sub rawOpen { die; }
    sub rawPrint { die; }
    sub rawClose { die; }
}

my $d01 = Display->new(StringDisplayImpl->new('Hello Japan!'));
my $d02 = CountDisplay->new(StringDisplayImpl->new('YOROSIKU'));

$d01->display();
$d02->display();
$d02->multiDisplay(10);