package Printable; sub print_on { my $self = shift; my($fh) = @_; print $fh $self->as_string; } sub as_string { $_[0]->value } sub new { my $proto = shift; my $scalar; my $self = bless \$scalar, ref($proto) || $proto; } sub set_value { my $self = shift; $$self = $_[0]; return $self; } sub value { ${$_[0]} } sub print { $_[0]->print_on(\*STDOUT) } package Decorator; use base 'Printable'; sub decorate { my $proto = shift; my($target) = @_; $self->new->set_target($target); } sub new { my $proto = shift; my $self = bless {}, ref($proto) || $proto; $self->init; return $self; } sub init { } package MultiString; use base 'Decorator'; sub count { my $self = shift; exists($self->{count}) ? $self->{count} : 1; } sub set_count { my $self = shift; $self->{count} = $_[0]; return $self; } sub as_string { my $self = shift; $self->target->as_string x $self->count; } package FormatBold; use base 'Decorator'; sub as_string { my $self = shift; '' . $self->target->as_string . ''; } package main; $thing = MultiString->decorate( FormatBold->decorate( Printable->new->set_value("Hello, world"); ) )->set_count(5); $thing->print;