NAME
Simple::Factory - a simple factory to create objects easily, with cache, autoderef and fallback supports
SYNOPSYS
use Simple::Factory;
my $factory = Simple::Factory->new(
'My::Class' => {
first => { value => 1 },
second => [ value => 2 ],
},
fallback => { value => undef }, # optional. in absent, will die if find no key
);
my $first = $factory->resolve('first'); # will build a My::Class instance with arguments 'value => 1'
my $second = $factory->resolve('second'); # will build a My::Class instance with arguments 'value => 2'
my $last = $factory->resolve('last'); # will build a My::Class instance with fallback arguments
DESCRIPTION
This is one way to implement the Factory Pattern. The main objective is substitute one hashref of objects ( or coderefs who can build/return objects ) by something more intelligent, who can support caching and fallbacks. If the creation rules are simple we can use Simple::Factory
to help us to build instances.
We create instances with resolve
method. It is lazy. If you need build all instances (to store in the cache) consider try to resolve them first.
If you need something more complex, consider some framework of Inversion of Control (IoC).
For example, we can create a simple factory to create DateTime objects, using CHI as cache:
my $factory = Simple::Factory->new(
build_class => 'DateTime',
build_method => 'from_epoch',
build_conf => {
one => { epoch => 1 },
two => { epoch => 2 },
thousand => { epoch => 1000 }
},
fallback => sub { epoch => $_[0] }, # fallback can receive the key
cache => CHI->new( driver => 'Memory', global => 1),
);
$factory->resolve( 1024 )->epoch # returns 1024
IMPORTANT: if the creation fails ( like some excetion from the constructor ), we will not call the fallback
. We expect some error handling from your side.
ATTRIBUTES
build_class
Specify the perl package ( class ) used to create instances. Using Method::Runtime
, will die if can't load the package.
This argument is required. You can omit by using the build_class
as a first argument of the constructor.
build_args
Specify the mapping of key => arguments, storing in a hashref.
This argument is required. You can omit by using the build_class
and build_args
as a first pair of arguments.
Important: if autoderef
is true, we will try to deref the value before use to create an instance.
fallback
The default behavior is die if we try to resolve an instance using one non-existing key.
But if fallback is present, we will use this on the constructor.
If autoderef
is true and fallback is a code reference, we will call the code and pass the key as an argument.
build_method
By default the Simple::Factory
calls the method new
but you can override and specify your own build method.
Will croak if the build_class
does not support the method on resolve
.
autoderef
If true ( default ), we will try to deref the argument present in the build_conf
only if it follow this rules:
will deref only references
if the reference is an array, we will call the
build_method
with@$array
.if the reference is a hash, we will call the
build_method
with%$hash
.if the reference is a scalar or other ref, we will call the
build_method
with$$ref
.if the reference is a glob, we will call the
build_method
with*$glob
.if the reference is a code, we will call the
build_method
with $code->( $key ) ( same thinf for the fallback )other cases (like Regexes) we will carp if it is not in
silence
mode.
silence
If true ( default is false ), we will omit the carp message if we can't autoderef
.
cache
If present, we will cache the result of the method resolve
. The cache should responds to get
, set
and remove
like CHI.
We will also cache fallback cases.
If we need add a new build_conf via add_build_conf_for
, and override one existing configuration, we will remove it from the cache if possible.
default: not present
inline
Experimental feature. useful to create multiple inline definitions. See resolve.
This feature can change in the future.
on_error
Change the default behavior of what happens if build one instance throws on error.
Accepts a coderef. You can also use three initial shortcuts ( will be coerce to coderef ): croak
, carp
and fallback
.
croak
will croak the exception + extra message about the key ( default ).carp
will just carp instead croak and return undef.fallback
will resolve the fallback ( but in case of exception will die - to avoid one potential deadlock ).
Example:
my $factory = Simple::Factory->new(
Foo => { ... },
fallback => -1,
on_error => "fallback" # in case of some exception, call the fallback
);
If one coderef was used, it will be called with one hashref as argument with three fields:
key
with the value of the keyfactory
one reference for the factory itselfexception
with the error message
Example:
my $factory = Simple::Factory->new(
Foo => { a => 1 },
on_error => sub { $logger->warn("error while resolve key '$_[0]->{key}' : '$_[0]->{exception}'; undef },
);
$factory->resolve("b"); # will call 'on_error', log the exception and return undef
METHODS
add_build_conf_for
usage: add_build_conf_for( key => configuration [, options ])
Can add a new build configuration for one specific key. It is possible add new or just override.
You can change the behavior using an hash of options.
Options: you can avoid override one existing configuration with not_override
and a true value.
Will remove cache
if possible.
Example:
$factory->add_build_conf_for( last => { foo => 1, bar => 2 }); # can override
$factory->add_build_conf_for( last => { ... }, not_override => 1); # will croak instead override
resolve
usage: resolve( key [, keys ] )
The main method. Will build one instance of build_class
using the build_conf
and build_method
.
Should receive a key and if does not exist a build_conf
will try use the fallback if specified, or will die ( confess ).
If the cache
attribute is present, will try to return first one object from the cache using the key
, or will resolve and store in the cache for the next call.
You can pass multiple keys. If the instance responds to resolve
method, we will call with the rest of the keys. It is useful for inline many factories.
Example:
my $factory = Simple::Factory->new(
'Simple::Factory' => {
Foo => {
build_class => 'Foo',
build_conf => {
one => 1,
two => 2,
}
},
Bar => {
Bar => {
first => { ... },
last => { ... },
}
}
}
);
my $object = $factory->resolve('Foo', 'one'); # shortcut to ->resolve('Foo')->resolve('one');
Or, using inline
experimental option.
my $factory = Simple::Factory->new(
'Simple::Factory'=> {
Foo => { one => 1, two => 2 },
Bar => { first => 0, last => -1},
},
inline => 1,
);
If we have some exception when we try to create an instance for one particular key, we will not call the fallback
. We use fallback
when we can't find the build_conf
based on the key.
get_fallback_for_key
this method will try to resolve the fallback. can be useful on on_error
coderefs. accept the same argument as resolve
.
SEE ALSO
- Bread::Board
-
A solderless way to wire up your application components.
- IOC
-
A lightweight IOC (Inversion of Control) framework
AUTHOR
Tiago Peczenyj <tiago (dot) peczenyj (at) gmail (dot) com>
BUGS
Please report any bugs or feature requests on the bugtracker website https://github.com/peczenyj/simple-factory-p5/issues