Hello,
I found myself writing out the same code for factory objects that provide
the loading/selecting of 'plugin' modules. Simple stuff - just annoying to
keep retyping the same load/lookup code.
I couldn't see anything obvious on CPAN (maybe MooseX::Object::Plugable
could be used but this seems more to be about applying plugins to a given
object rather than providing a factory?). I've typed out a synopsis and I
figured I would post it here since if it isn't already in MooseX I could
well be doing something stupid (I figure it's better to know these things).
Failing that - I figured it might save someone else some typing.
Comments welcome - cheers,
Ian
=head1 NAME
MooseX::PluginFactory - provides easy access to custom plugins
=head1 SYNOPSIS
Define factory object
package My::Algorithm::ParamFactory;
use My::Moose;
with 'MooseX::PluginFactory';
sub plugin_base { 'My::Algorithm::Param' }
Define plugin modules however you want to:
# plugin base class
package My::Algorithm::Param;
use My::Moose;
has 'foo',
is => 'ro', isa => 'Int', required => 1;
has 'bar',
is => 'ro', isa => 'Int', required => 1, default => 0;
sub to_string {
my $self = shift;
sprintf "foo: %s, bar: %s", $self->foo, $self->bar
}
# plugins
package My::Algorithm::Param::Set1;
use My::Moose;
extends 'My::Algorithm::Param';
sub BUILDARGS { { foo => 4 } }
package My::Algorithm::Param::Set2;
use My::Moose;
extends 'My::Algorithm::Param';
sub BUILDARGS { { foo => 10, bar => 4 } }
Elsewhere...
$param_set1 = My::Algorithm::ParamFactory->plugin_get( 'set1' );
# equivalent to:
# My::Algorithm::Param::Set1->new;
$param_set1->to_string;
# foo: 4, bar: 0
=head1 DESCRIPTION
I found myself writing the same code to help create factories that manage
the creation of a
bunch of related "plugin" modules, e.g.
My::View::Text
My::View::HTML
My::View::XML
My::ViewFactory->get( 'HTML' ); # My::View::HTML
This kind of thing is useful when you want to coerce objects from strings:
package My::App;
use Moose::Util::TypeConstraints;
subtype 'My.View'
=> as 'Object'
=> where { $_->isa( My::View ) };
coerce 'My.View'
=> from 'Str'
=> via { My::ViewFactory->new( $_ ) };
has 'view',
isa => 'My.View', coerce => 1;
Which allows:
$app = My::App->new( view => 'HTML' );
$app->view; # My::View::HTML
This is kind of like getting the benefits of string validating (e.g. enum
from Moose::Util::TypeConstraints), however you also
get the benefits of storing instantiated objects rather than just strings.