jffry has asked for the wisdom of the Perl Monks concerning the following question:

I asked this question earlier in the week, and thanks for the advice, Monks and Monkesses, but I'm guessing that what I really need in this case is a Factory class. That is, I need to tell a functon/method/class/whatever, "Give me X number of objects of Z type." Is that what a Factory class is for?

I apologize in advance for such a basic not really Perl-specific question, but this is such a fantastic forum of minds. I'm glad to be here.

  • Comment on Do I need a Factory Class At This Point?

Replies are listed 'Best First'.
Re: Do I need a Factory Class At This Point?
by halley (Prior) on Feb 02, 2006 at 17:01 UTC
    Exactly.
    use Factory; use Fruit; my $apple = Factory->newObject("Apple"); $apple->doSomethingAnyGenericFruitCanDo();
    Mind you, it's so easy to create objects by package name in Perl that the Factory pattern is often unnecessary. You should only use it when it would be inconvenient to specifically use Apple. Usually this is because new class types may be created even after the program's engine code is finished, such as class types created by the application's user. Another classic purpose for Factories is when every instance of a given class must be somehow registered or managed; in this case, the Factory stores an internal record of each object it produces.

    --
    [ e d @ h a l l e y . c c ]

Re: Do I need a Factory Class At This Point?
by ikegami (Patriarch) on Feb 02, 2006 at 17:53 UTC
    Factories are usually used by objects to create child objects. The purpose of the factory is to avoid having to hardcode a class name. For example,
    package Tree; sub add_item { my ($self, $item) = @_; my $parent_node = ...; $parent_node->add(new Node($item)); }

    would be transfored into the following when using a factory:

    package Tree; sub add_item { my ($self, $item) = @_; my $node_factory = $self->{node_factory}; my $parent_node = ...; $parent_node->add($node_factory->create($item)); } sub set_node_factory { my ($self, $node_factory) = @_; $self->{node_factory} = $node_factory; } package NodeFactory; # Overridable sub create { shift(@_); return Node->new(@_); }

    But that's pretty useless in Perl, since it lacks the typing of Java. In Perl, you could easily accept a class name (e.g. 'Node') or a code ref (e.g. sub { Node->new(@_) }) instead of a factory.

      OK, I am getting enough of what you are telling me to understand your point.

      I know some of the basics of OO, and I know how to use Perl as a replacement for awk. I jumped straight into using Object::InsideOut without ever writing up my own simple Perl classes, so I'm ignorant of Perl OO implementation basics. Yesterday on the drive home I figured out that is why some of my questions come from left field and why this advice is more opaque to me than I'd like.

      What still mystifies me about your code is the use of the ... operator. This is just a range operator right? I've read every paragraph of perlop that contains the '...' string, but I still don't understand you use of that operator.

      Thanks.

        Such diligence! But in this case, ... simply means "There's code missing here." How one finds where to insert a node into a tree wasn't relevant to the topic at hand.
Re: Do I need a Factory Class At This Point?
by Roy Johnson (Monsignor) on Feb 02, 2006 at 17:40 UTC
    I don't think so. I think you just want something like
    # Initialize a new Z object for each element of @inits my @obj_array = map {$z->new($_)} @inits;
    or if $z is an object of the desired type rather than a class name,
    # Initialize a new object of the same type as $z for each element of @ +inits my @obj_array = map {ref($z)->new($_)} @inits;

    Caution: Contents may have been coded under pressure.
Re: Do I need a Factory Class At This Point?
by dragonchild (Archbishop) on Feb 02, 2006 at 19:15 UTC
    To provide a counterpoint to the "Perl doesn't usually need factories" replies, I use a factory in PDF::Template to manage the nodename-to-classname mapping. This way, I can do something like:
    my $obj = $factory->create_element( $node_name, @args ); # Check to see if $obj represents a 'foobar' node if ( $obj->isa( 'foobar' ) ) { # Do something }
    This is important to me for three reasons:
    1. My users can register new nodenames and the factory manages that
    2. I have some classes that can handle more than one nodename. For example, IF and CONDITIONAL are aliases to each other and are both handled by PDF::Template::Element::Conditional.
    3. In most of the code, I need to differentiate what's a container (can have children) and what's an element (can't have children). However, in the parsing code, I don't care about that (because validation is handled somewhere else).
    Does that help?

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?