Mooseでデザパタ - Bridgeパターン

#!/usr/bin/env perl
use strict;
use warnings;

# Bridge パターン
#
# Java言語で学ぶデザインパターンと同様の例題をPerl+Mooseで記述した。
#
# coded by Dann
#
{

    package Display;
    use Moose;
    has impl => (
        is       => 'rw',
        required => 1,
        handles  => {
            printf => 'raw_print',
            close  => 'raw_close',
            open   => 'raw_open'
        }
    );

    sub display {
        my $self = shift;
        $self->open;
        $self->printf;
        $self->close;
    }
}

{

    package CountDisplay;
    use Moose;
    extends 'Display';

    sub multi_display {
        my ( $self, $times ) = @_;
        $self->open;
        for ( 1 .. $times ) {
            $self->printf;
        }
        $self->close;
    }
}
{

    package DisplayImpl;
    use Moose::Role;
    requires 'raw_open';
    requires 'raw_print';
    requires 'raw_close';
}
{

    package StringDisplayImpl;
    use Moose;
    use Moose::Autobox;
    use Perl6::Say;
    with 'DisplayImpl';
    has string => ( is => 'rw', isa => 'Str', required => 1 );
    has width => (
        is      => 'rw',
        isa     => 'Str',
        lazy    => 1,
        default => sub { shift->string->length },
    );

    sub raw_open {
        my $self = shift;
        $self->print_line;
    }

    sub raw_print {
        my $self = shift;
        say "|" . $self->string . "|";
    }

    sub raw_close {
        my $self = shift;
        $self->print_line;
    }

    sub print_line {
        my $self = shift;
        print "+";
        for ( 1 .. $self->width ) {
            print "-";
        }
        say "+";
    }
}

sub main {
    my $d1 = Display->new(
        impl => StringDisplayImpl->new( string => "Hello, Japan." ) );
    my $d2 = CountDisplay->new(
        impl => StringDisplayImpl->new( string => "Hello, World." ) );
    my $d3 = CountDisplay->new(
        impl => StringDisplayImpl->new( string => "Hello, Universe." ) );
    $d1->display;
    $d2->display;
    $d3->display;
    $d3->multi_display(5);
}

main();

Moose的には

  • interfaceとしてのRole
  • handlesで処理を委譲

がポイントでしょうか