Skip to content

Instantly share code, notes, and snippets.

@xenoterracide
Created November 11, 2012 04:22
Show Gist options
  • Select an option

  • Save xenoterracide/4053667 to your computer and use it in GitHub Desktop.

Select an option

Save xenoterracide/4053667 to your computer and use it in GitHub Desktop.
Inversion of Control and Dependency Injection example
use 5.014;
use warnings;
use Class::Load 'load_class';
package PaymentGateway {
use Moose;
sub submit {
return int( rand(2) );
}
__PACKAGE__->meta->make_immutable;
}
package Order {
use Moose;
sub make_payment {
my $self = shift;
return $self->_payment_gateway->submit( $self );
}
has _payment_gateway => (
isa => 'Object',
is => 'ro',
required => 1,
);
__PACKAGE__->meta->make_immutable;
}
package AppContainer {
use Moose;
extends 'Bread::Board::Container';
use Bread::Board; #import sugar
sub _build_config {
my $self = shift;
# hardcode for example
return {
username => 'foo',
password => 'bar',
};
}
has _config => (
isa => 'HashRef',
is => 'ro',
lazy => 1,
builder => '_build_config',
);
sub BUILD {
my $self = shift;
# container can take a container as a parameter. if you do this it
# will simply add to the container it tooks as a paramter
# this will be our root container /
container $self => as {
# subcontainer path to will be /model
container model => as {
# order uses constructor injection
service order => (
class => 'Order',
dependencies => {
# use full path
_payment_gateway =>
depends_on('/remote/payment_gateway'),
},
);
};
# another subcontainer /service
container remote => as {
service username => $self->_config->{username};
service password => $self->_config->{password};
service payment_gateway => (
class => 'PaymentGateway',
# we don't need more than one instance
lifecycle => 'Singleton',
dependencies => {
username => depends_on('username'),
password => depends_on('password'),
},
);
};
};
}
__PACKAGE__->meta->make_immutable;
}
package Controller {
# this could be any framework controller
use Moose;
has _c => (
isa => 'Bread::Board::Container',
is => 'ro',
);
sub process_order {
my $self = shift;
my $order = $self->_c->resolve( service => '/model/order' );
if ( $order->make_payment ) {
say 'payment succeeded';
}
else {
say 'payment failed';
}
}
__PACKAGE__->meta->make_immutable;
}
my $app = AppContainer->new({ name => 'app' });
# controller has not idea there's only one app containerr
my $controller = Controller->new( _c => $app );
for ( my $i = 0; $i < 10 ; $i++ ) {
$controller->process_order;
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment