views:

881

answers:

5

Hi,

I was working with java code that is supposedly using the Factory pattern, but I'm not completely convinced by the pattern.

My code does this:

// the factory
class SomeFactoryImpl {
   Set<SomeClass> getSomeListOfObjects();
}

And somewhere in the code:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

The point I'm pondering is, if factory classes don't have a static create() method, then one will need to instantiate a factory, which IMO should be just as complex as instantiating an object itself.

I don't consider the arguement that such a factory can return collections of objects to be produced is good enough. I feel there can be cleaner work arounds, if a factory instance needs to be created before actually creating objects from the factory.

I feel that it is better if the create method a static method of the factory class. But I'm also sure that my opinion is not completely "correct".

So can the SO community give examples where instantiating a Factory object is better than using static create methods?

Also, I came across an answer to a similar question, which listed these links and the answer: so I need to know clearly the difference between FactoryMethodPattern, FactoryMethod and CreationMethod with code examples.

jrh

+1  A: 

I guess, a static method for the object creation is the most popular approach, but there are also some use-cases where first creating a factory instance makes sense. For example if you want to combine it with a registry (where multiple registries should be allowed to co-exist).

Also if the factory relies on some dynamic context information (database connections, ...) it is in my opinion better to let a factory-instance handle this.

Horst Gutmann
+1  A: 

First of all you are forgetting the main aim of the factory pattern, I opened the book of the gang of four and it states:

"Define an interface for creating an objet, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses."

This means that actually you define an interface, so SomeFactoryImpl should actually implement an interface defined somewhere else. This comes handy when you've got many objects that need to be instantiated but you don't want to care about which kind of object they are.. For example I used them to develop a remote swing application in which the client downloaded through serialization the definition of some classes that didn't exist in the client VM. Every class defined a subclass of JPanel which its specific view but when reaching the client I had to find a way to istantiate these classes without knowing them so I used a factory pattern to call the factory class and let it instantiate my uknown object (althrough it is extending a subclass of JPanel defined by me). Another example would be the generation of case-specific object to suit your needs. For example (like stated in wikipedia page related to this design pattern) you can think a factory that builds object and then another factory for the same kind of object but used to generate "fake objects" that will fail some kind of unit testing.

However you can solve your specific problem with static methods too but think about splitting the part that generates items from the part that uses them in a big project. Of course who is developing the client part should just know which factory interface is used and know just this to use all the objects definet in the other part.

Creation Pattern is a sort of 'facility' pattern used just to define custom versions of constructors without worrying using standard definition (having the name of the method equal to the name of the class) but it's nothing special. Just a different way to istantiate objects.. the creation pattern actually doesn't solve any kind of specific problem (excluding constructors with same number and kind of arguments).

Jack
I think his SomeFactoryImpl actually is an implementation of an interface, although it was not explicitly stated. (Well actually the line SomeFactory factory = new SomeFactoryImpl(); is explicit enough).
subtenante
A: 

Here's why I create instances of factory objects

  1. it allows me to create a factory, configure it (to create blue widgets vs. red widgets etc.) and then have it available to create my blue widgets, red widgets on demand. Note that this is distinct from having a RedWidgetFactory, BlueWidgetFactory. The configuration is orthogonal to the type(s) of objects being created
  2. it reduces possible threading issues that you may encounter having one factory (accessed via a static method) used throughout your system. This is perhaps a little defensive, but I've found that's a good mindset to have (especially in sizable systems). Of course it depends how your objects are created (e.g. does your factory create underlying components that are shared)
Brian Agnew
I agree with the threading issues and concurrency part, but my smelling powers tell me that RedWidgetFactory is a better idea than factory.setProductColor('red'). Do you/Don't you agree?
Here Be Wolves
Perhaps it's a bad example. But imagine if you had 10,000 colours. You wouldn't have a different factory class for each one. Whereas you may have a different class and factory for creating discrete sets of objects with differing behaviours.
Brian Agnew
A: 

IMO, the code you have is indeed a proper specimen of the GoF Abstract Factory pattern, even if its use is not completely optimal. If I recall correctly, the GoF book describes the relationship between factories (SomeFactory, SomeFactoryImpl) and products (SomeClass) but leaves the specifics of instantiating factories open.

If what you have is an internal API that isn't going to be widely used, what you have is probably sufficient. Otherwise, you could:

  1. Have another class (a "factory manager" so to speak) select your factory implementation based on a parameter (e.g., the DriverManager in JDBC), or other context information.
  2. Use some sort of dependency injection framework.

If going with #1, I personally usually try and model it after JDBC, where:

  • Driver would be the abstract factory
  • Connections, Statements etc are products
  • DriverManager (not specified in GoF book explicitly) is the utility class that selects a factory for you based on the JDBC URL passed in

(In this case, the DriverManager goes ahead and creates the product for you also, if you use the getConnection(...) methods, as most do.)

To tie it back to your question, one could arguably use JDBC by calling

new OracleDriver().connect(...)

But as your pointed out, this is sub-optimal, and somewhat defeats the purpose of using the abstract factory pattern.

This problem used to bother me a lot too, until I realized one day that that pattern actually does not explicitly talk about how factories are created.

I hope this answers your question.

Jack Leow
+1  A: 

Using an instance of a factory shows the real benefits when combined with dependency injection.

So in your example, instead of:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

You would have:

public ThisClass(SomeFactory someFactory) {
    this.factory = someFactory;
}

then later...

{ ...
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

Some points:

  • In this circumstance your class does not have any reference to a concrete factory, and doesn't need to know about SomeFactoryImpl, it only knows about the abstracted SomeFactory.
  • In this case the factory instance that's being passed around can be configured on an instance basis, rather than a static basis, which tends to be (in my opinion) a nicer way to deal with it. If you can make the factory instance immutable then you can really cut down the multi-threading worries.
  • Having a static call to give you an instance isn't really much better, the reference to the class that creates it is still a concrete implementation detail, it's just higher up - though that may make it high enough to solve your problem.

I know this only addresses a subset of your question...

Grundlefleck
+1 Oh, yes.. combine this with a DI framework and testing would become pretty much a cakewalk. Thanks!
Here Be Wolves