observer pattern in perl
Obverver Pattern
https://en.wikipedia.org/wiki/Observer_pattern
implement the example in Perl
use Std; #for signature and postfix deref
package Observable {
use Moose;
use Std;
has 'observers' => ( is => 'rw', default => sub { [] } );
#TODO: this can be delegated
sub register_observer($self, $observer) {
push $self->observers->@*, $observer;
}
sub notify_observers($self, @rest) {
$_->notify(@rest) for $self->observers->@*;
}
}
package Observer1 {
use Moose;
use Std;
sub register($self, $observable) {
$observable->register_observer($self);
}
sub notify {
my $self = shift;
my $message = shift;
say $message;
}
}
package Observer2 {
use Moose;
use Std;
sub register($self, $observable) {
$observable->register_observer($self);
}
sub notify {
my $self = shift;
my $message = shift;
say $message;
}
}
my $subject = Observable->new();
my $observer1 = Observer1->new->register($subject);
my $observer2 = Observer2->new->register($subject);
$subject->notify_observers('test');
emulate the EventEmiter in Node js
use Std;
package Obserable {
use Moose::Role;
use Std;
has 'events' => ( is => 'rw', default => sub { +{} } );
sub on($self, $name, $cb) {
$self->events->{$name} = [] if not defined $self->events->{$name};
push $self->events->{$name}->@*, $cb;
}
sub emit($self, $name, @rest ) {
if ( my $cb_aref = $self->events->{$name} ) {
$_->(@rest) for @$cb_aref;
}
}
}
package SimpleEE {
use Moose;
with 'Obserable';
}
my $emitter = SimpleEE->new();
$emitter->on( 'greet', sub ($name) { say( 'Hello, ' . $name . '!' ); } );
$emitter->on( 'greet', sub ($name) { say( 'World, ' . $name . '!' ); } );
$emitter->emit( 'greet', $_ ) for qw( foo bar baz);