[Moscow.pm] Strategy ("Стратегия") и "Декоратор"(Decorator/Wrapper) реализация на Perl

Orlovsky Alexander nordicdyno на yandex.ru
Чт Июл 10 00:54:52 PDT 2008


10.07.08, 10:01, "Shrub Alexey" <ashrub на agava.com>:

> Can't bless non-reference value at ./decorator.pl line 31
> поправил, получил
> Can't use string ("f") as an ARRAY ref while "strict refs" in use at 
> ./decorator.pl line 120.
> дальше смотреть поленился, что не так?

При копи-пасте потерялись обратные слеши, вот рабочий исходный код:


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

main();
exit;

sub main {
    my $printer =
        VerticalDecorator->new(
            ReverseDecorator->new(
#                SimpleArrayPrinter->new(
                PrettyArrayPrinter->new(
                    data     => [ [ 'a' .. 'f' ], [ 1 .. 6 ], [ 'g' .. 'l' ] ],
                    splitter => ' ',
                    format   => {
                        title => 'Data Title',
                    },
                )
            )
        );
{ # interface description (for Decorators and Components) and implementation:)
package ArrayPrinter;
    sub new {
        my $class = shift;
        my %params = @_;
        return bless \%params, $class;
    }

    sub print_data { } 

    sub set_data {
        my $self = shift;
        my $ref = shift;
        $self->{data} = $ref;
    }

    sub get_data {
        my $self = shift;
        return $self->{data};
    }
}

{ # Concrete component SimpleArrayPrinter
package SimpleArrayPrinter;
use base 'ArrayPrinter';

    sub print_data {
        my $self = shift;
        for my $a ( @{ $self->get_data() } ) {
            print join($self->{splitter}, @{$a}), "\n";
        }
    }
}

{ # Concrete component PrettyArrayPrinter
package PrettyArrayPrinter;
use base 'ArrayPrinter';
    use Data::Dumper;
    use Pretty::Table;

    sub print_data {
        my $self = shift;
        my $pt = Pretty::Table->new(
            %{ $self->{'format'} }
        );
        $pt->set_data_ref( $self->get_data() );
        print $pt->output();
    }
}

{ # Decorator's base class
package Decorator;
use base 'ArrayPrinter';
    sub new {
        my $class = shift;
        my $component = shift;
        my $self = bless { component => $component }, $class;
        return $self;
    }

    sub print_data {
        my $self = shift;
        $self->{component}->print_data();
    }

    sub set_data {
        my $self = shift;
        $self->{component}->set_data(@_);
    }

    sub get_data {
        my $self = shift;
        return $self->{component}->get_data(@_);
    }
}

{ # Concrete decorator: VerticalDecorator
package VerticalDecorator;
use base 'Decorator';
    use Data::Dumper;

    sub new {
        my $class = shift;
        my $self = $class->SUPER::new(@_);
        $self->_vertical();
        return $self;
    }

    sub _vertical {
        my $self = shift;
        my @result;
        for my $a ( @{ $self->{component}->get_data() } ) {
            my $i = 0;
            for my $elem ( @{$a} ) {
                push @{ $result[$i] }, $elem;
                $i++;
            }
        }
        $self->{component}->set_data( \@result );
    }
}

{ # Concrete decorator: ReverseDecorator
package ReverseDecorator;
use base 'Decorator';

    sub new {
        my $class = shift;
        my $self = $class->SUPER::new(@_);
        $self->_reverse_data();
        return $self;
    }

    sub _reverse_data {
        my $self = shift;
        my @data;
        for my $a ( @{ $self->{component}->get_data() } ) {
            push @data, [ reverse @{$a} ];
        }
        $self->{component}->set_data( \@data );
    }
}


Подробная информация о списке рассылки Moscow-pm