Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it OK to pass parameters to a Factory method?

One of the ways to implement Dependency Injection correctly is to separate object creation from business logic. Typically, this involves using a Factory for object creation.

Up until this point, I've never seriously considered using a Factory so I apologize if this question seems a little simplistic:

In all the examples of the Factory Pattern that I've run across, I always see very simple examples that have no parameterization. For example, here's a Factory stolen from Misko Hevery's excellent How To Think About the "new" Operator article.

class ApplicationBuilder {
  House build() {
    return new House(new Kitchen(
               new Sink(),
               new Dishwasher(),
               new Refrigerator())
           );
  }
}

However, what happens if I want each house that I build to have a name? Am I still using the Factory pattern if I re-write this code as follows?

class ApplicationBuilder {
  House build( const std::string & house_name) {
    return new House( house_name,
                      new Kitchen(new Sink(),
                                  new Dishwasher(),
                                  new Refrigerator())
                    );
  }
}

Note that my Factory method call has changed from this:

ApplicationBuilder builder;
House * my_house = builder.build();

To this:

ApplicationBuilder builder;
House * my_house = builder.build("Michaels-Treehouse");

By the way: I think the concept of separating object instantiation from business logic is great, I'm just trying to figure out how I can apply it to my own situation. What confuses me is that all the examples I've seen of the Factory pattern never pass any parameters into the build() function.

To be clear: I don't know the name of the house until the moment before I need to instantiate it.

like image 400
Runcible Avatar asked Mar 05 '09 16:03

Runcible


People also ask

Why would one use the factory method rather than just using a constructor?

A factory method can return an already created object, unlike a constructor, which always creates a new instance.

When should you use a factory method?

The Factory Method pattern is generally used in the following situations: A class cannot anticipate the type of objects it needs to create beforehand. A class requires its subclasses to specify the objects it creates. You want to localize the logic to instantiate a complex object.

What is the difference between factory and factory method?

Use the Factory method when you want to make a Framework where you want to take a control from the creation of the Object to the management of that Object. That's unlike the Simple factory, where you only care about the creation of a product, not how to create and manage it.

Can Factory method static?

The static factory methods are methods that return an instance of the native class. The static factory method has names that clarify the code, unlike the constructors. In the static factory method, we do not need to create a new object upon each invocation i.e object can be cached and reused if required.


2 Answers

I've seen quite a lot of examples that use a fixed set of arguments, like in your name example, and have used them myself too and i can't see anything wrong with it.

However there is a good reason that many tutorials or small articles avoid showing factories that forward parameters to the constructed objects: It is practically impossible to forward arbitrary number of arguments (even for a sane limit like 6 arguments). Each parameter you forward has to be accepted as const T& and T& if you want to do it generic.

For more complicated examples, however, you need an exponentially growing set of overloads (for each parameter, a const and a nonconst version) and perfect forwarding is not possible at all (so that temporaries are forwarded as temporaries, for example). For the next C++ Standard that issue is solved:

class ApplicationBuilder {
  template<typename... T>
  House *build( T&&... t ) {
    return new House( std::forward<T>(t)...,
                      new Kitchen(new Sink(),
                                  new Dishwasher(),
                                  new Refrigerator())
                    );
  }
};

That way, you can call

builder.build("Hello", 13);

And it will return

new House("Hello", 13, new Kitchen(new Sink(...

Read the article i linked above.

like image 135
Johannes Schaub - litb Avatar answered Oct 05 '22 14:10

Johannes Schaub - litb


Not only is is acceptable, but it's common to pass parameters to a factory method. Check out some examples. Normally the parameter is a type telling the factory what to make, but there's no reason you can't add other information you need to build an object. I think what you're doing is fine.

like image 40
Bill the Lizard Avatar answered Oct 05 '22 16:10

Bill the Lizard