Object-oriented – Using a Simple/Static Factory vs. instantiating directly: new Thing() vs. factory.createThing() – what’s the benefit

design-patternsfactoryobject-oriented

Here are two ways to instantiate an object:

Option 1:

Thing thing = new Thing();

Option 2: (the factory is a Static Factory, but it could also be a Simple Factory).

Thing thing = ThingFactory.createThing();

Where:

class ThingFactory(){
    public static Thing createThing(){
        return new Thing();
    }
}

Option 2 is said to be better, because using a factory decouples the client code from the concrete implementation of the class it's instantiating.

However what difference does it actually make if I use new Thing() or factory.createThing()? The only difference between the two options is that the instantiation code is moved to a different place.

As I explained above I know the 'academic' explanation to why using a factory is 'better', but I don't actually see the practical benefit. In both cases, the client knows exactly what it wants: a Thing. The only difference is the exact line of code: new Thing() or factory.createThing().


More sophisticated factories, I can see their benefit. For example using the Abstract Factory pattern, I could create different Factory subclasses that instantiate different concrete implementations of Thing, and inject the suitable Factory to the client at runtime, without the client worrying about the concrete implementation it receives. BlueThingFactory instantiates BlueThing, RedThingFactory instantiates RedThing, but the client only cares that it receives a Thing.

This is with more sophisticated factories.

But I'm unable to see the benefit of using a simple factory as in the example I described. All it does is move new Thing() to a different place. I don't understand the benefit of this.


Please explain to me the actual benefits of using a simple factory.

Best Answer

  • Factory methods might allow for better named interfaces. new Range(0, n - 1) isn't as readable as Range.upto(n). Note also that in some languages (Perl, Python, Ruby), new isn't a keyword but at most a convention, so picking an appropriate method name for the constructor is preferable.

  • Factories (not singletons or similar constructs via static methods) simplify testing and increase flexibility. Here it is important to balance YAGNI with planning for change (and a DI container is so much easier to change than recompiling everything after running s/ClassA/ClassB/ over your whole source).

  • In some languages, the constructor can't be part of an interface. Here, we need to offer a method that wraps the constructor. This is important in some cases like a Monad pattern.

  • Factory methods are a great way of enforcing programming to an interface, not an implementation, as the user has no control over the specific class being returned.