Question

I've read the following article about Factory pattern here
Please refer only to the short section Class Registration - avoiding reflection.
This version is implementing reduced coupling between factory and concrete products without reflection.

So, I've tried to implement this version myself without success.
The reason is that static initializers of concrete product classes weren't launched, therefore they didn't registered in the hashmap, so calling the ProductFactory instance with createProduct method didn't succeed.

When I initialized some concrete classes in the client outside of the factory this led the static initializer to launch and the concrete class registered well. After that I called ProductFactory.getInstance().createProduct(productID) and concrete class was finally created.

So the questions are:

Do this site example missing something?
How are the static initializers triggered in the given example?

Code that relevant for this example is(from site):

abstract class Product
{
    public abstract Product createProduct();
    ...
}

class OneProduct extends Product
{
    ...
    static
    {
        ProductFactory.instance().registerProduct("ID1", new OneProduct());
    }
    public OneProduct createProduct()
    {
        return new OneProduct();
    }
    ...
}

class ProductFactory
{
    public void registerProduct(String productID, Product p)    {
        m_RegisteredProducts.put(productID, p);
    }

    public Product createProduct(String productID){
        return ((Product)m_RegisteredProducts.get(productID)).createProduct();
    }
}
Was it helpful?

Solution

Yes, they're missing something, just like in the reflection example the class must be loaded before by the client or it won't get registered in the factory, which i don't think is a very clean approach, since the factory clients will have to load the class before asking for it, making the productId pretty much useless and coupling the clients with the particular product implementation.

I like what they (unfairly) call the noob implementation i think it's the most widely used and for good reasons, it's simpler and with it you can actually encapsulate and centralize the creation of objects without the client knowing anything about it but the id of the particular product (no direct class loading), the other implementations are useful when you're planning to let the ProductFactory clients to register new product implementations without having to modify code in the factory itself, but in most cases you'll find that modifying the factory when a new implementation comes in is not such a big deal.

So, to summarize, the noob implementation is not noobie at all, it's just simpler and suited to certain use cases. And in general, in cases like this, i don't think there are better or worse or noobie implementations, there are just different needs and use cases.

hint: It's cleaner and safer to use an enum instead of strings for productId, that is, of course, if you can modify the enum every time a new product implementation comes in.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top