18

I'm trying to succinctly describe when to use a factory, for both myself and my team. I ran across the following related questions, which helped somewhat:

Based on these links, and a bunch of other sources (listed at the bottom), I've come up with the following:

When to use the abstract factory pattern:

  • when you use an interface var or the 'new' operator
    • e.g. User user = new ConcreteUserImpl();
  • and the code you are writing should be testable / extensible at some point

Explanation:

  • interfaces by their very nature imply multiple implementations (good for unit testing)
  • interface vars imply OCP- and LSP-compliant code (support sub-classing)
  • use of the 'new' operator breaks OCP/DI, because highly-coupled classes are hard to test or change

"Do I create a factory for every object type? That seems excessive."

  • no, you can have one (or a few) factories that produce a lot of (usually related) object types
  • e.g. appFactory.createUser(); appFactory.createCatalog(); etc.

When NOT to use a factory:

  • the new object is very simple and unlikely to be sub-classed
    • e.g. List list = new ArrayList();
  • the new object is not interesting to test
    • has no dependencies
    • performs no relevant or long-running work
    • e.g. Logger log = new SimpleLogger();

References:


My question is: is my summary accurate, and does it make sense? Is there anything I've overlooked?

Thanks in advance.

Community
  • 1
  • 1
Luke
  • 2,151
  • 3
  • 17
  • 15
  • I hate reviving old threads, but... I disagree that loggers should be new'd up as above. I often run different loggers in different test environments. I configure the environment to use a specific logger and inject it into objects that log. (I might even inject arrays of loggers.) – aridlehoover Mar 19 '13 at 23:35

3 Answers3

5

I'd also say don't use a factory when you have a particular implementation that you want. To continue the List example, I know that I want an ArrayList because I'm doing random access. I don't want to rely on a factory getting this right when I can do it myself.

Conversely, when I don't want to know about the concrete subclass then I can use a factory and let it worry about which object to actually instantiate.

I guess I'd suggest that you add a bullet to the "when to use the abstract factory pattern" that says "and you don't really care which concrete subclass you get", and the converse to "when not to use a factory".

EDIT: Be careful to avoid the general-purpose tool-building factory factory factory.

Cameron Skinner
  • 51,692
  • 2
  • 65
  • 86
  • Ok - let's say I wanted the specific advantages of a cached thread pool: ExecutorService pool = Executors.newCachedThreadPool(); However, in my unit tests (for whatever reason) I'm not interested in the results of the work done in the pool, and I don't want to have to wait for the work to finish every time I run my tests. Wouldn't I then still use a factory so I could stub / mock out my thread pool for tests? It seems to me that when you consider testing, you want to think of **most** of your code as not caring about the actual implementation lest you write untestable code. – Luke Dec 02 '10 at 18:52
  • Yes, that's correct. Generally most of your code doesn't care about the actual implementation. Choosing between `ArrayList` and `LinkedList` is one of the few times that you do care because they have different performance characteristics. You're right: for testing it's best to ignore the actual implementation as much as possible. – Cameron Skinner Dec 02 '10 at 23:45
3

In general, use it when you want to be able to switch of implementation by external configuration.

JDBC and JAXP are excellent examples. For more examples, check this answer.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
1

Abstract Factory pattern provides with a way to encapsulate concrete factories that share some commonality with each other, meaning they implement same interface/abstract class.

You need to use factory pattern whenever you want to control the initialization of your objects, instead of giving the control to the consumer.

dexter
  • 7,063
  • 9
  • 54
  • 71