NAME

Venus::Factory - Factory Class

ABSTRACT

Factory Class for Perl 5

SYNOPSIS

package main;

use Venus::Factory;

my $factory = Venus::Factory->new;

# $factory->class('Venus::Path');

# $factory->build;

# bless(.., "Venus::Path")

DESCRIPTION

This package provides an object-oriented factory pattern and mechanism for building objects using dependency injection.

ATTRIBUTES

This package has the following attributes:

name

name(string $name) (string)

The name attribute is read/write, accepts (string) values, is optional, and defaults to undef.

Since 4.15

name example 1
# given: synopsis;

my $name = $factory->name('log');

# "log"
name example 2
# given: synopsis;

# given: example-1 name

$name = $factory->name;

# "log"

INHERITS

This package inherits behaviors from:

Venus::Kind::Utility

INTEGRATES

This package integrates behaviors from:

Venus::Role::Buildable

Venus::Role::Encaseable

Venus::Role::Tryable

Venus::Role::Catchable

Venus::Role::Throwable

METHODS

This package provides the following methods:

args

args(any @args) (Any)

The args method accepts arguments and merges them with any "arrayref", "hashref", or "list" registered in the current configuration and returns the result. Returns a list in list context.

  • If an "arrayref" exists and the argment is an arrayref, the values are merged by appending the arguments provided to the end of the registered arrayref.

  • If a "hashref" exists and the argment is a hashref, the values are merged without overriding the keys and values from the registered hashref.

  • If a "list" exists and the argment is a list of values, the values are merged by appending the arguments provided to the end of the registered list.

Since 4.15

args example 1
# given: synopsis

package main;

my @args = $factory->args;

# ()
args example 2
# given: synopsis

package main;

my $args = $factory->args;

# undef
args example 3
# given: synopsis

package main;

my $args = $factory->args({path => '/root'});

# {path => "/root"}
args example 4
# given: synopsis

package main;

$factory->value({path => '/boot'});

my $args = $factory->args({path => '/root'});

# {path => "/root"}
args example 5
# given: synopsis

package main;

$factory->value({path => '/boot'});

my $args = $factory->args;

# {path => "/boot"}
args example 6
# given: synopsis

package main;

$factory->value(name => 'example');

my @args = $factory->args;

# ('name', 'example')
args example 7
# given: synopsis

package main;

$factory->register('data.home')->value('/home');

$factory->register('data.root')->value('/root');

$factory->list('data.home', 'data.root');

my @args = $factory->args;

# ('/home', '/root')
args example 8
# given: synopsis

package main;

$factory->register('data.home')->value('/home');

$factory->register('data.root')->value('/root');

$factory->list('data.home', 'data.root');

my @args = $factory->args('/boot');

# ('/home', '/root', '/boot')
args example 9
# given: synopsis

package main;

$factory->register('data.home')->value('/home');

$factory->register('data.root')->value('/root');

$factory->arrayref('data.home', 'data.root');

my $args = $factory->args;

# ['/home', '/root']
args example 10
# given: synopsis

package main;

$factory->register('data.home')->value('/home');

$factory->register('data.root')->value('/root');

$factory->arrayref('data.home', 'data.root');

my $args = $factory->args(['/boot']);

# ['/home', '/root', '/boot']
args example 11
# given: synopsis

package main;

$factory->register('data.home')->value('/home');

$factory->register('data.root')->value('/root');

$factory->hashref({home => 'data.home', root => 'data.root'});

my $args = $factory->args;

# {home => '/home', root => '/root'}
args example 12
# given: synopsis

package main;

$factory->register('data.home')->value('/home');

$factory->register('data.root')->value('/root');

$factory->hashref({home => 'data.home', root => 'data.root'});

my $args = $factory->args({boot => '/boot'});

# {home => '/home', root => '/root', boot => '/boot'}

arrayref

arrayref(arrayref $data) (arrayref)

The arrayref method modifies the current configuration and registers an arrayref where each value is a string or arrayref representing arguments to be passed to "build", each value is resolved and the resulting arrayref merged with the "value" upon resolution.

Since 4.15

arrayref example 1
# given: synopsis;

my $arrayref = $factory->arrayref;

# undef
arrayref example 2
# given: synopsis;

my $arrayref = $factory->arrayref('path');

# bless(..., "Venus::Factory")
arrayref example 3
# given: synopsis;

$factory->arrayref('path');

my $arrayref = $factory->arrayref;

# ['path']
arrayref example 4
# given: synopsis;

my $arrayref = $factory->arrayref(['path', '/var/log'], ['path', '/tmp/log']);

# bless(..., "Venus::Factory")

assert

assert(string $expr) (Venus::Factory)

The assert method modifies the current configuration and registers a type expression to be used to validate the resulting object upon resolution.

Since 4.15

assert example 1
# given: synopsis;

my $assert = $factory->assert;

# undef
assert example 2
# given: synopsis;

my $assert = $factory->assert('Example');

# bless(..., "Venus::Factory")
assert example 3
# given: synopsis;

$factory->assert('Example');

my $assert = $factory->assert;

# "Example"

attach

attach(string $name, Venus::Factory $data) (Venus::Factory)

The attach method adds an existing "detached" container to the registry and returns container.

Since 4.15

attach example 1
# given: synopsis

package main;

my $attach = $factory->attach;

# bless(..., "Venus::Factory")
attach example 2
# given: synopsis

package main;

my $attach = $factory->attach('path', Venus::Factory->new->class('Venus::Path'));

# bless(..., "Venus::Factory")

builder

builder(coderef $callback) (coderef)

The builder method modifies the current configuration and registers a callback invoked during resolution which the resolved object is passed through. The return value of the callback will be returned by "resolve".

Since 4.15

builder example 1
# given: synopsis;

my $builder = $factory->builder;

# undef
builder example 2
# given: synopsis;

my $builder = $factory->builder(sub{});

# bless(..., "Venus::Factory")
builder example 3
# given: synopsis;

$factory->builder(sub{});

my $builder = $factory->builder;

# sub{}

cache

cache(hashref $cache) (hashref)

The cache method gets and sets a store to be used by all derived containers where objects will be cached upon resolution.

Since 4.15

cache example 1
# given: synopsis;

my $cache = $factory->cache;

# undef
cache example 2
# given: synopsis;

my $cache = $factory->cache({});

# bless(..., "Venus::Factory")
cache example 3
# given: synopsis;

$factory->cache(sub{});

my $cache = $factory->cache;

# sub{}

cached

cached(boolean $bool) (Venus::Factory)

The cached method modifies the current configuration and denotes that the object should be cached upon resolution.

Since 4.15

cached example 1
# given: synopsis;

my $cached = $factory->cached;

# undef
cached example 2
# given: synopsis;

my $cached = $factory->cached(true);

# bless(..., "Venus::Factory")
cached example 3
# given: synopsis;

$factory->cached(true);

my $cached = $factory->cached;

# true

callback

callback(any @args) (Venus::Factory)

The callback method modifies the current configuration and denotes that a coderef containing the resolved object should be returned upon resolution.

Since 4.15

callback example 1
# given: synopsis;

my $callback = $factory->callback;

# sub{...}
callback example 2
# given: synopsis;

$factory->class('Venus::Path');

my $callback = $factory->callback('.');

# sub{...}

chain

chain(string | within[arrayref, string] @chain) (Venus::Factory)

The chain method method modifies the current configuration and registers a string or arrayref representing subsequent method calls to be chained upon resolution.

Since 4.15

chain example 1
# given: synopsis;

my $chain = $factory->chain;

# undef
chain example 2
# given: synopsis;

my $chain = $factory->chain('step_1');

# bless(..., "Venus::Factory")
chain example 3
# given: synopsis;

$factory->chain('step_1');

my $chain = $factory->chain;

# ["step_1"]
chain example 4
# given: synopsis;

$factory->chain('step_1', 'step_2');

my $chain = $factory->chain;

# ["step_1", "step_2"]
chain example 5
# given: synopsis;

$factory->chain('step_1', 'step_2', ['step_3', 1..4]);

my $chain = $factory->chain;

# ["step_1", "step_2", ["step_3", 1..4]]

class

class(string $class) (Venus::Factory)

The class method is shorthand for calling "package", "assert", and "method" with the argument "new".

Since 4.15

class example 1
# given: synopsis;

my $class = $factory->class;

# undef
class example 2
# given: synopsis;

my $class = $factory->class('Venus::Path');

# bless(..., "Venus::Factory")
class example 3
# given: synopsis;

$factory->class('Venus::Path');

my $class = $factory->class;

# "Venus::Path"

clone

clone() (Venus::Factory)

The clone method clones the current configuration and returns a container not attached to the registry.

Since 4.15

clone example 1
# given: synopsis

package main;

my $clone = $factory->clone;

# bless(..., "Venus::Factory")
clone example 2
# given: synopsis

package main;

$factory->class('Venus::Path')->name('path');

my $clone = $factory->clone;

# bless(..., "Venus::Factory")
clone example 3
# given: synopsis

package main;

$factory->class('Venus::Path')->builder(sub{$_->absolute})->name('path');

my $clone = $factory->clone;

# bless(..., "Venus::Factory")

constructor

constructor(any @data) (defined)

The constructor method modifies the current configuration and registers a callback invoked during resolution which is passed the package, if any, and the resolved dependencies (and/or arguments), if any. The return value of the callback will be considered the resolved object.

Since 4.15

constructor example 1
# given: synopsis;

my $constructor = $factory->constructor;

# undef
constructor example 2
# given: synopsis;

my $constructor = $factory->constructor(sub{});

# bless(..., "Venus::Factory")
constructor example 3
# given: synopsis;

$factory->constructor(sub{});

my $constructor = $factory->constructor;

# sub{}

detach

detach(string $name) (maybe[Venus::Factory])

The detach method removes an existing container from the registry and returns container. The detached container will still have access to the registry to resolve dependencies. To detach from the registry use "reset".

Since 4.15

detach example 1
# given: synopsis

package main;

my $detach = $factory->detach('path');

# undef
detach example 2
# given: synopsis

package main;

$factory->register('path')->class('Venus::Path');

my $detach = $factory->detach('path');

# bless(..., "Venus::Factory")

dispatch

dispatch(string $name) (Venus::Factory)

The dispatch method modifies the current configuration and denotes the subroutine that should be dispatched to upon resolution.

Since 4.15

dispatch example 1
# given: synopsis;

my $dispatch = $factory->dispatch;

# undef
dispatch example 2
# given: synopsis;

my $dispatch = $factory->dispatch('do_something');

# bless(..., "Venus::Factory")
dispatch example 3
# given: synopsis;

$factory->dispatch('do_something');

my $dispatch = $factory->dispatch;

# "do_something"

extend

extend(string $name) (Venus::Factory)

The extend method copies the details of the configuration specified to the current configuration.

Since 4.15

extend example 1
# given: synopsis;

$factory->register('path')->class('Venus::Path');

my $extend = $factory->extend;

# bless(..., "Venus::Factory")
extend example 2
# given: synopsis;

$factory->register('path')->class('Venus::Path');

my $extend = $factory->register('temp')->extend('path');

# bless(..., "Venus::Factory")

function

function(string $name) (Venus::Factory)

The function method modifies the current configuration and denotes that object resolution should result from a function call using the function name provided.

Since 4.15

function example 1
# given: synopsis;

my $function = $factory->function;

# undef
function example 2
# given: synopsis;

my $function = $factory->function('do_something');

# bless(..., "Venus::Factory")
function example 3
# given: synopsis;

$factory->function('do_something');

my $function = $factory->function;

# "do_something"

hashref

hashref(hashref $data) (hashref)

The hashref method modifies the current configuration and registers an hashref where each value is a string or arrayref representing arguments to be passed to "build", each value is resolved and the resulting hashref is merged with the "value" upon resolution.

Since 4.15

hashref example 1
# given: synopsis;

my $hashref = $factory->hashref;

# undef
hashref example 2
# given: synopsis;

my $hashref = $factory->hashref({path => 'path'});

# bless(..., "Venus::Factory")
hashref example 3
# given: synopsis;

$factory->hashref({path => 'path'});

my $hashref = $factory->hashref;

# {path => "path"}
hashref example 4
# given: synopsis;

$factory->hashref({
  tmplog => ['path', '/tmp/log'],
  varlog => ['path', '/var/log'],
});

my $hashref = $factory->hashref;

# {tmplog => ["path", "/tmp/log"], varlog => ["path", "/var/log"]}

list

list(string | arrayref @data) (string | arrayref)

The list method modifies the current configuration and registers a sequence of values where each value is a string or arrayref representing arguments to be passed to "build", each value is resolved and the resulting list is merged with the "value" upon resolution.

Since 4.15

list example 1
# given: synopsis;

my $list = $factory->list;

# undef
list example 2
# given: synopsis;

my $list = $factory->list('path');

# bless(..., "Venus::Factory")
list example 3
# given: synopsis;

$factory->list('path');

my @list = $factory->list;

# ("path")
list example 4
# given: synopsis;

$factory->list(['path', '/var/log'], ['path', '/tmp/log']);

my @list = $factory->list;

# (['path', '/var/log'], ['path', '/tmp/log'])

method

method(string $name) (Venus::Factory)

The method method modifies the current configuration and denotes that object resolution should result from a method call using the method name provided.

Since 4.15

method example 1
# given: synopsis;

my $method = $factory->method;

# undef
method example 2
# given: synopsis;

my $method = $factory->method('do_something');

# bless(..., "Venus::Factory")
method example 3
# given: synopsis;

$factory->method('do_something');

my $method = $factory->method;

# "do_something"

new

new(hashref $data) (Venus::Factory)

The new method returns a Venus::Factory object.

Since 4.15

new example 1
package main;

use Venus::Factory;

my $factory = Venus::Factory->new;

# bless(..., "Venus::Factory")

package

package(string $name) (Venus::Factory)

The package method modifies the current configuration and denotes that object resolution should be derived from the package name provided.

Since 4.15

package example 1
# given: synopsis;

my $package = $factory->package;

# undef
package example 2
# given: synopsis;

my $package = $factory->package('Example');

# bless(..., "Venus::Factory")
package example 3
# given: synopsis;

$factory->package('Example');

my $package = $factory->package;

# "Example"

protocol

protocol(string $name) (Venus::Factory)

The protocol method modifies the current configuration and denotes the subroutine dispatch protocol that should be used upon resolution.

Since 4.15

protocol example 1
# given: synopsis;

my $protocol = $factory->protocol;

# undef
protocol example 2
# given: synopsis;

my $protocol = $factory->protocol('method');

# bless(..., "Venus::Factory")
protocol example 3
# given: synopsis;

$factory->protocol('method');

my $protocol = $factory->protocol;

# "method"

register

register(string $name) (Venus::Factory)

The register method registers and returns a new container (dependency resolver).

Since 4.15

register example 1
# given: synopsis;

my $register = $factory->register('path');

# bless(..., "Venus::Factory")

registry

registry(hashref $store) (hashref)

The registry method returns a hashref representing all registered containers.

Since 4.15

registry example 1
# given: synopsis;

my $registry = $factory->registry;

# undef
registry example 2
# given: synopsis;

my $registry = $factory->registry({});

# bless(..., "Venus::Factory")
registry example 3
# given: synopsis;

$factory->registry({});

my $registry = $factory->registry;

# {}

reset

reset(string $name) (any)

The reset method resets a property of the current configuration based on the name provided. If no name is provided this method will reset all properties. If a property name is provided this method returned the value of the reset property. If no property name is provided this method returns the invocant.

Since 4.15

reset example 1
# given: synopsis

package main;

my $reset = $factory->reset;

# bless(..., "Venus::Factory")
reset example 2
# given: synopsis

package main;

$factory->class('Venus::Path')->name('path');

my $reset = $factory->reset;

# bless(..., "Venus::Factory")
reset example 3
# given: synopsis

package main;

$factory->class('Venus::Path')->name('path');

my $reset = $factory->reset('assert');

# "Venus::Path"
reset example 4
# given: synopsis

package main;

$factory->name('path');

$factory->class('Venus::Path');

# my $reset = $factory->reset('package');

# "Venus::Path"

resolve

resolve(any @args) (any)

The resolve method resolves the current configuration and returns the constructed object based on the configuration. Any arguments provided (or registered "values") are merged with any registered "arrayref", "hashref", or "list" values.

Since 4.15

resolve example 1
# given: synopsis;

$factory->class('Venus::Path');

my $resolve = $factory->resolve;

# bless(..., "Venus::Path")
resolve example 2
# given: synopsis;

$factory->class('Venus::Path');

my $resolve = $factory->resolve('.');

# bless(..., "Venus::Path")
resolve example 3
# given: synopsis;

my $resolve = $factory->register('path')->class('Venus::Path')->resolve('.');

# bless(..., "Venus::Path")
resolve example 4
# given: synopsis;

$factory->class('Venus::Log');

my $resolve = $factory->resolve;

# bless(..., "Venus::Log")
resolve example 5
# given: synopsis;

$factory->register('log')->class('Venus::Log');

my $resolve = $factory->resolve;

# undef
resolve example 6
# given: synopsis;

my $resolve = $factory->register('date')->class('Venus::Date')->value(570672000)->resolve;

# bless(..., "Venus::Date")
resolve example 7
# given: synopsis;

my $resolve = $factory->register('date')
  ->class('Venus::Date')->value({year => 1988, month => 2, day => 1})->resolve;

# bless(..., "Venus::Date")
resolve example 8
# given: synopsis;

my $resolve = $factory->register('date')
  ->class('Venus::Date')->value(year => 1988, month => 2, day => 1)->resolve;

# bless(..., "Venus::Date")
resolve example 9
# given: synopsis;

my $resolve = $factory->register('date')
  ->class('Venus::Date')->builder(sub{$_->mdy})->value(570672000)
  ->assert('string')
  ->resolve;

# "02-01-1988"
resolve example 10
# given: synopsis;

my $resolve = $factory->register('greeting')
  ->class('Venus::String')->builder(sub{$_->titlecase})
  ->assert('string')
  ->resolve('hello world');

# "Hello World"
resolve example 11
# given: synopsis;

$factory->register('string')->class('Venus::String')->assert('string');

my $string = $factory->retrieve('string');

$string->builder(sub{
  my ($factory, $object) = @_;
  return $object->titlecase;
});

my $resolve = $string->resolve('hello world');

# "Hello World"
resolve example 12
# given: synopsis;

my $resolve = $factory->register('md5')->package('Digest::MD5')->function('md5_hex')->resolve;

# "d41d8cd98f00b204e9800998ecf8427e"
resolve example 13
# given: synopsis;

my $resolve = $factory->register('md5')->package('Digest::MD5')->function('md5_hex')->resolve('hello');

# "5d41402abc4b2a76b9719d911017c592"
resolve example 14
# given: synopsis;

$factory->cache({});

my $secret = $factory->register('secret')->cached(true)->package('Digest::MD5')->function('md5_hex');

# $secret->resolve(rand);

# "fa95053a9a204800ced194ffa3fc84bc"

# $secret->resolve(rand);

# "fa95053a9a204800ced194ffa3fc84bc"
resolve example 15
# given: synopsis;

my $error = $factory->register('error')->class('Venus::Error');

$error->constructor(sub{
  my ($factory, $package, $method, @args) = @_;
  return $package->$method(@args)->do('name', 'on.factory.build');
});

$error->resolve;

# bless(..., "Venus::Error")
resolve example 16
# given: synopsis;

my $resolve = $factory->register('data.home')->value('/root')->resolve;

# "/root"
resolve example 17
# given: synopsis;

my $resolve = $factory
  ->register('data.home')->value('/root')
  ->register('path.home')->class('Venus::Path')->list('data.home')
  ->resolve;

# bless(..., "Venus::Path")

retrieve

retrieve(string $name) (Venus::Factory)

The retrieve method returns a registered container (dependency resolver) using the name provided. If no argument is provided the invocant is returned.

Since 4.15

retrieve example 1
# given: synopsis;

$factory->register('path')->class('Venus::Path');

my $retrieve = $factory->retrieve;

# bless(..., "Venus::Factory")
retrieve example 2
# given: synopsis;

$factory->register('path')->class('Venus::Path');

my $retrieve = $factory->retrieve('path');

# bless(..., "Venus::Factory")

routine

routine(string $name) (Venus::Factory)

The routine method modifies the current configuration and denotes that object resolution should result from a routine call (or package call) using the subroutine name provided.

Since 4.15

routine example 1
# given: synopsis;

my $routine = $factory->routine;

# undef
routine example 2
# given: synopsis;

my $routine = $factory->routine('do_something');

# bless(..., "Venus::Factory")
routine example 3
# given: synopsis;

$factory->routine('do_something');

my $routine = $factory->routine;

# "do_something"

value

value(any @data) (any)

The value method method modifies the current configuration and registers value(s) to be provided to the "method", "function", or "routine" upon resolution.

Since 4.15

value example 1
# given: synopsis;

my $value = $factory->value;

# undef
value example 2
# given: synopsis;

my $value = $factory->value('hello world');

# bless(..., "Venus::Factory")
value example 3
# given: synopsis;

$factory->value('hello world');

my @value = $factory->value;

# ("hello world")
value example 4
# given: synopsis;

$factory->value({value => 'hello world'});

my @value = $factory->value;

# ({value => 'hello world'})
value example 5
# given: synopsis;

$factory->value(1..4);

my @value = $factory->value;

# (1..4)

AUTHORS

Awncorp, awncorp@cpan.org

LICENSE

Copyright (C) 2022, Awncorp, awncorp@cpan.org.

This program is free software, you can redistribute it and/or modify it under the terms of the Apache license version 2.0.