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

#!/usr/bin/env perl
use strict;
use warnings;
use Perl6::Say;

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

{

    package Printable;
    use Moose::Role;
    requires 'set_printer_name';
    requires 'get_printer_name';
    requires 'printstr';
}

{

    package Printer;
    use Moose;
    use Perl6::Say;
    with 'Printable';
    has name => ( is => 'rw', isa => 'Str', required => 1 );

    sub BUILD {
        my $self = shift;
        $self->heavy_job(
            "Printerのインスタンス(" . $self->name . ")を生成中" );
    }

    sub printer {
        my $self = shift;
        $self->heavy_job("Printerのインスタンスを生成中");
    }

    sub set_printer_name {
        my ( $self, $name ) = @_;
        $self->name($name);
    }

    sub get_printer_name {
        my $self = shift;
        $self->name;
    }

    sub printstr {
        my ( $self, $string ) = @_;
        say '=== ' . $self->name . ' ===';
        say $string;
    }

    sub heavy_job {
        my ( $self, $msg ) = @_;
        print $msg;
        for ( 0 .. 5 ) {
            sleep(1);
            print '.';
        }
        say ' ';
        say '完了。';
    }

}

{

    package PrinterProxy;
    use Moose;
    with 'Printable';

    has name => ( is => 'rw', isa => 'Str', required => 1 );
    has real => ( is => 'rw' );

    sub set_printer_name {
        my ( $self, $name ) = @_;
        if ( $self->real ) {
            $self->real->set_printer_name($name);
        }
        $self->name($name);
    }

    sub get_printer_name {
        my $self = shift;
        $self->name;
    }

    sub printstr {
        my ( $self, $string ) = @_;
        $self->realize;
        $self->real->printstr($string);
    }

    sub realize {
        my $self = shift;
        $self->real( Printer->new( name => $self->name ) ) unless ( $self->real );
    }

}

sub main {
    my $p = PrinterProxy->new( name => "Alice" );
    say "名前は現在" . $p->get_printer_name . "です。";
    $p->set_printer_name("Bob");
    say "名前は現在" . $p->get_printer_name . "です。";
    $p->printstr("Hello, world.");
}

main();

See also: