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

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

# Visitor パターン
#
# Fileクラスはシステムで定義してあるのでFile以外のクラス名とすること
#
# 印字内容は検討中
#

{

    package FileNode;
    use Moose;
    use Perl6::Say;

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

    sub visit {
        my $self = shift;
        say "File : " . $self->name . " size " . $self->size . " byte";
    }
}

{

    package DirectoryNode;
    use Moose;
    use MooseX::ClassAttribute;
    use Moose::Autobox;
    use Perl6::Say;

    class_has 'currentdir' => ( is => 'rw', isa => 'Str', default  => '' );
    has name               => ( is => 'rw', isa => 'Str', required => 1 );
    has list => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );

    sub add {
        my ( $self, $entry ) = @_;
        $self->list->push($entry);
    }

    sub visit {
        my $self = shift;

        say __PACKAGE__->currentdir . "/" . $self->name . " ";
        my $savedir = __PACKAGE__->currentdir;
        __PACKAGE__->currentdir(
            __PACKAGE__->currentdir . "/" . $self->name );
        foreach my $item ( @{ $self->list } ) {
            $item->visit;
        }
        __PACKAGE__->currentdir($savedir);

    }
}

sub main {
    my $f1 = FileNode->new( name => "F1", size => 128 );
    my $d1 = DirectoryNode->new( name => "D1" );
    my $f2 = FileNode->new( name => "F2", size => 256 );
    my $d2 = DirectoryNode->new( name => "D2" );
    my $f3 = FileNode->new( name => "F3", size => 64 );
    my $d3 = DirectoryNode->new( name => 'D3' );
    my $f4 = FileNode->new( name => "F4", size => 1024 );
    my $f5 = FileNode->new( name => "F5", size => 256 );

    $d1->add($f1);
    $d1->add($d2);
    $d1->add($f2);
    $d2->add($f3);
    $d2->add($f4);
    $d2->add($d3);
    $d3->add($f5);

    $d1->visit;
}

main();

See also:
http://www.ceres.dti.ne.jp/~kaga/rubyvisitor.txt