May 06, 2003

Interfaces and factory explosion

As I mentioned before, using dynamic mocks in testing forces you to look at using interfaces everywhere. This is partly due to the EasyMock implementation which can only mock interfaces, but also just a side effect (and I think a good one) of using mocks.

So if you're using interfaces everywhere how do you actually create usable objects? You seem to have two options:

  1. Make the interface transparent so you know what implementations exist.
  2. Make the interface opaque and use a Factory to create objects. The Factory knows what implementations exist but abstracts the details.

As an example: the first option is what the Collections API does. When you want to create a new object you use something like:

 List fooList             = new ArrayList();
 Set fooSet               = new HashSet();
 Collection fooCollection = new LinkedList();
 Collection fooCollection = new TreeSet();

So you're aware of the implementation details (the class name) when you create the object. A factory hides the details from you, either abstracting it behind a simple name or choosing the implementation details from something else like runtime configuration.

The problem I'm having is that if you're using interfaces everywhere, even when you've only got a single implementation, then you're forcing the user to be aware of the details:

 ShoppingCart cart = new ShoppingCartImpl();
 Product prod      = new ProductImpl();
 Order order       = new OrderImpl();

But if you use a factory you'll have single-use factories everywhere!

 ShoppingCart cart = CartFactory.getCart();
 Product prod      = ProductFactory.getProduct();
 Order order       = OrderFactory.getOrder();

Another option is creating a factory per area of the system and putting all your methods there:

 ShoppingCart cart = OrderFactory.getCart();
 Product prod      = OrderFactory.getProduct();
 Order order       = OrderFactory.getOrder();

The last option seems workable but also kind of clunky... Is this done often?

Next: TV out of campaigns
Previous: Learning to use dynamic mocks