views:

107

answers:

3

So, coming upon the subject of Factories, I'm wondering how they are set up.

From where I stand, I can see 3 types of Factories:

All In One

A factory that basically contains all of the classes used in an application. It feels like it is just having a factory for the sake of having a factory, and doesn't really feel structured.

Example (Where ClassA, Class B, and ClassC have nothing in common except being in the same App):

class Factory
{
 public static function buildClassA()
 public static function buildClassB()
 public static function buildClassC()
}

Code samples provided are in PHP. However, this question is language-agnostic.

Built-In Factory

The next one is mixing in static functions with the regular functions in order to make special creation patterns (see this question)

Example:

class ClassA
{
 public static function buildClass()
 public function __construct()
}

Factory On-the-Side

The last one I can think of is having a factory for individual classes, or individual sets of classes. This just seems to variable to be used in an uniform manner.

Example (Where ClassA, B, and C are related, and 1, 2, and 3 are related):

class FactoryAlpha
{
 public static function buildClassA()
 public static function buildClassB()
 public static function buildClassC()
}

class FactoryNumeric
{
 public static function buildClass1()
 public static function buildClass2()
 public static function buildClass3()
}

My question is: Are all of these bad ideas, are any of them bad ideas? Are there other ways of creating factories? Are any of these actually good ideas? What is a good/best way to create Factories.

+5  A: 

The point of a factory seems to be to have the code that uses it not need to know which concrete class will be constructed (this should be handled by configuring the factory). That seems to rule out "All-in One" and "Factory-on-the-Side".

I like the approach that Java libraries often use: You have a static method that creates the Factory. The Factory has a getInstance method that creates the instance. This gives you two points of configuration (via system properties): The default FactoryImpl has a number of settings, such as the class it should produce, and if these configuration options are not enough, you can also swap out the FactoryImpl altogether.

As for "All-in One" vs "Factory-on-the-Side", a Factory should not produce unrelated classes I think. Again, it Java terms, every factory produces instances of a certain interface.

"All-in-One" sounds like something that should be replaced with Dependency Injection (where you have a container that produces all kinds of instances and injects them into the application).

Thilo
+1 excellent answer
mxmissile
+2  A: 

If you are really interested in "Preferred technologies", I'd replace them all with Dependency Injection.

If that seems to heavy, just remember that you may not be seeing every use for your factory so don't "New" a hard-coded class in your factory. Instead, have a "Setter" that can specify what class needs to be injected.

This will come in handy later when you are unit testing and need to start injecting mock classes.

But as you make this more general, abstract and reusable, you'll end up back at DI. (Just don't say I didn't warn you)

Bill K
A: 

There's really just two standard sorts of factories, at least according to GOF and the slew of patterns books that followed: The basic Factory, and the Abstract Factory.

A Factory generally returns a concrete instance that the caller refers to through an interface, like so:

// createWidget() here instantiates a BigWidget or SmallWidget or whatever the context calls for
IWidget widget = WidgetFactory.createWidget(someContextValue);

Using a factory with an interface in this way keeps the caller from being coupled into a specific type of the returned object. Following the venerable Single Responsibility Principle, a factory should do one thing, that is, return a concrete instance of the interface that was called for, and nothing more. A basic factory should only have the job of creating one type of object.

An Abstract Factory, on the other hand, can be thought of as a factory of factories, and might be closer to what you were thinking of as an "all in one" factory. An Abstract Factory is usually configured at start-up to return a group of related factories, for instance factories that might create a particular family of GUIs depending on a given context. This is an example of Dependency Inversion that has largely been replaced by using IOC containers like Spring.

Dave Sims