6

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.

2
  • Of course, now it's generally frowned on to use a static factory in favor of an injected one. Factories allow instantiation to use caches if the language doesn't support it natively. It'd also allow for parameter checking without starting object instantiation. Some stuff might be language dependent... Commented May 17, 2014 at 12:59
  • Look at the code for new Integer(42) vs Integer.valueOf(42) and consider that simple factory.
    – user40980
    Commented May 17, 2014 at 13:23

6 Answers 6

10
  • 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.

3
  • Thanks for answering. So with Java, in what cases should I make a factory, and in what cases should I instantiate directly?
    – Aviv Cohn
    Commented May 17, 2014 at 17:29
  • @Prog Explicit instantiation should not be part of the API of a library – offer factory methods instead. This doesn't add much complexity but (if done correctly) saves you from having to deprecate classes in future versions. Internally, do whatever you like – you can always refactor this without changing the interface. You might still end up using some form of dependency injection – either in the form of constructor injection (which doesn't scale) or a full-blown factory (which isn't that much boilerplate). On the other hand, you probably ain't gonna need it.
    – amon
    Commented May 17, 2014 at 18:37
  • 2
    @amon I disagree that "Instatiation should not be part of the API of a library" in every case. Requiring clients to use factory methods makes your objects less subclass-friendly for your clients. Sometimes this is good and sometimes not - you have to consider the trade-offs involved in each case. Commented May 18, 2014 at 6:53
6

fact.createThing(args) allows the factory to return a subclass of Thing (dependency injection), or a pooled object of Thing.

Both of these have their advantages; the subclass option allows Thing to be abstract or an interface, and allows it to be mocked in testing.

The pool option is only handy when Thing uses a limited resource or is expensive to allocate.

5
  • If the object isn't expensive to instantiate, and it is unlikely that it will be subclassed in the future - should I still encapsulate it's instantiation in a factory?
    – Aviv Cohn
    Commented May 17, 2014 at 13:22
  • Basically what you're saying is that I should encapsulate a class' instantiation in a simple factory in one of two cases: 1- it's likely that subclasses or more 'kinds' of this object will be added in the future to the system, or 2- it's expensive to instantiate so it's better to enforce always getting it from a pool. Correct?
    – Aviv Cohn
    Commented May 17, 2014 at 13:26
  • @Prog just the mockability can make it worth it Commented May 17, 2014 at 13:26
  • @Prog expensive can also mean you instantiate a lot of them, like java's Integer.valueof are cached because with auto boxing you'd get a lot of instantiations Commented May 17, 2014 at 13:29
  • I see. So when I add a new class to the system, and I suspect I'm going to add subclasses of this class in the future, it's a good idea to create a factory for this class, so in the future it will be easier to add it's subclasses to the system. Right?
    – Aviv Cohn
    Commented May 17, 2014 at 13:30
3

There is none. Actually, using factory in this simple case might be counterproductive, because you are adding new class for zero benefit. And any kind of argument that says there is a benefit shifts from this simple method call to more sophisticated factory. Which as you said, do have benefits.

So according to YAGNI, if you don't expect the class of instance to be supplied from the outside or require some kind of special creation logic, there is absolutely no need to create a specific factory class. Actually, constructors are meant to be such simple factories.

I believe massive use of factories and design patterns like this is great example of cargo-cult programming. Where people use patterns haphazardly without actually knowing what kind of problems the patterns are meant to solve. And it is one of the reasons why Java is considered bloated.

1

Suppose you later come up with a version 2 of class Thing, e.g. Thing2. Instead of finding all the "new Thing" and change all of them to "new Thing2" you only need to change one instruction inside the factory.

I find it usefull with unit test where I change the factory to create the mock class (e.g. "new ThingMock"). The rest of the code remains the same.

Maybe the content of class Thing is read by internet so the method "createThing" can make a download of an object, or the new class can be loaded by a file, have random contents, etc. In theese cases there are many instruction inside createThing and it would be hard to make such change in all the instructions "new Thing".

1
  • this post is rather hard to read (wall of text). Would you mind editing it into a better shape?
    – gnat
    Commented May 17, 2014 at 17:36
1

It's "better", because you get fewer dependencies.

One of the worst things in software development is dependencies. Dependencies makes it very difficult to modify the software later on. Circular dependencies are even worse.

When you say new Thing() your client code now relies on the concrete class of thing. You have created a hard dependency from your client code to a very specific class, Thing.

When you say factory.CreateThing() any class that supplies the required interface can be used, and you client code no longer has a dependency to a concrete class.

But choosing which is "better" is a balance of many factors, and introducing factories for all your domain concepts will add other complexities to the code, and take time more to write. So it may be better from an architectural point of view, but not necessarily better from a practical point of view, if the complexity of the application does not benefit significantly from this abstraction.

1

If it's a simple object with a simple factory (like your example) then there is no advantage. I would be very leery of putting it in a factory (just in case vs YAGNI).

Things get interesting as the system changes and that simple object starts gathering behavior.

Adding an argument

When I add an argument to the constructor, I'm faced with a decision. Overload the constructor or change all the client code to use this new argument.

  • If it's optional, then overloading the constructor feels natural.

But what if this is now a required field?

  • If the object in question is a value object, then I've likely created dozens of them in my tests. At this point I almost always create a test-only factory for that value object so I can keep adding default test data without modifying lots of tests. This can be applied in the general case, but it's also a smell if you need a factory for every kind of test, what are you really testing?

  • If it's not a value object then I'm likely to add the argument everywhere, hopefully I haven't made too many of these.

Adding a second/third argument

At this point I should have a good idea of what this object is.

  • If it's a value object, then I just roll with the previous strategy. I wouldn't necessarily create a "factory" but it seems like I need some centralized place to create these values. This is often the case when translating data from one format to what my system needs.

  • If it is something else, how many places do I instantiate this code? If just one place, just add the argument in place. That's natural, it's where you discovered you needed this one more thing.

  • If it's in lots of places, does it make sense to use this object in all those places? If it's something like a logger, then yes it does. Time to build a factory.

  • If it's something domain-specific without cross-cutting-concerns then I need to take a hard look. Why is this thing useful in so many places? Is it doing too much? Split it into the concerns that each dependency is needed for.

  • If it's tightly focused but needs a lot of things to do it's job then a factory seems appropriate. Sometimes it's a thing like validation rules. You can work towards centralizing that, but a layered defense often makes sense. One other angle you can look at is if all the arguments being passed in perhaps belong together, like in a ParameterObject or something more appropriate.

Mixing in some behavior at construction time

Need object pooling? Sharing a connection? Need a singleton? Need to add debugging/logging? This is the natural fit for factories.

Creating specialized objects with arguments supplied

My personal preference for factories is to create expressive names. This is especially useful when following a dependency injection type style.

StormMaker.createThunderStorm()  // new Storm(80, 20, 360000, Thunder, Lightning)
StormMaker.createTornado()       // new Storm(70, 100, 60000, Lightning)
StormMaker.createBlizzard()      // new Storm(30, 30, 43200000)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.