#!/usr/bin/perl -l use lib '/PATH/TO/DesignPatterns-Perl/lib/'; package Model; use Moose; extends 'OODP::Observer'; has state => ( is => 'ro', isa => 'Num', default => 1 ); sub update { my ($self, $newval) = @_; $self->set_state( $newval ); } package View; use Moose; extends 'OODP::Composite', 'OODP::Subject'; sub notify { my $self = shift; $self->SUPER::notify( @_ ); $self->update_display; } sub update_display { my $self = shift; for my $child (values %{ $self->get_children }) { $child->update_display } } package View::FH; use Moose; use IO::File; use IO::Handle; extends 'View'; has '+name' => ( default => 'view' ); has mode => ( is => 'ro', isa => 'Str', default => '>' ); has filename => ( is => 'ro', isa => 'Str' ); has filehandle => ( is => 'ro', isa => 'IO::Handle', default => sub { IO::Handle->new_from_fd( fileno(STDOUT), 'w' ) } ); sub BUILD { my $self = shift; if ($self->get_filename) { $self->{filehadle} = IO::File->new( $self->get_mode . $self->get_filename ); } } sub DEMOLISH { my $self = shift; $self->get_filehandle->close if $self->get_filehandle; unlink $self->get_filename if $self->get_filename && -z $self->get_filename; } sub update_display { my $self = shift; my $fh = $self->get_filehandle; print $fh $_->get_state for @{ $self->get_observers }; $self->SUPER::update_display( @_ ); } package Controller; use Moose; extends 'OODP::Context'; has '+strategy' => ( handles => ['algorithm'], default => sub {Adder->new} ); has model => ( is => 'ro', handles => ['get_state'], default => sub {Model->new} ); has view => ( is => 'ro', handles => ['notify'], default => sub {View::FH->new} ); sub BUILD { my $self = shift; $self->{view}->attach( $self->{model} ) } sub context { my ($self,$val) = @_; $self->algorithm( $self->get_state, $val ) } sub run { my $self = shift; $self->notify( $self->context( $_ ) ) for @_; } package Adder; use Moose; extends 'OODP::Strategy'; use Data::Dumper; sub algorithm { $_[1] + $_[2] } package Subtractor; use Moose; extends 'OODP::Strategy'; sub algorithm { $_[1] - $_[2] } package main; use Data::Dumper; use IO::File; Controller->new( strategy => Subtractor->new )->run( 1 .. 10 ); Controller->new( view => View::FH->new( filename => 'out.txt', mode => '>>' ) )->run( 1 .. 10 ); print `cat out.txt`; Controller->new( strategy => Subtractor->new, view => View::FH->new( filename => 'out.txt', mode => '>>' ) )->run( 1 .. 10 ); print `cat out.txt`; print `rm out.txt`;