Principles, Patterns, and Practices: The Factory Pattern Blog



    Static Factory
    Abstract Factory
    Problems with Abstract Factory
    Factory Method
    Factory Overuse

    There is a principle of object-oriented design known as theDependency Inversion Principle (DIP). This principle tells us that we should try to avoid depending on things that are concrete. For example, given the choice between holding a reference to a List or its derivative LinkedList, we should choose the base class List.

    In other words, rather than writing:

    LinkedList balls = new LinkedList();

    We should write:

    List balls = new LinkedList();

    The reason for this should be obvious. We can passballs around as a List to any function or object that takes a List argument. Later, if we decide to change the definition of balls to anArrayList, we need only change one line of code.

    The DIP says: "Depend on abstractions, not on concretions." This is just another way of expressing the old maxim of information hiding. In this case we are hiding the true type of an object from all of its users.

    But what about the new statement above? It specifically uses the concrete class LinkedList. This clearly violates the DIP. Indeed, the statement List balls = new LinkedList(); is quixotic. It tilts at windmills by flagrantly exposing the concrete type of balls and then pretending to hide it.

    If we only create the balls list in one place, then at least we can claim to be hiding its type from the rest of the application, even if we do expose it here in one place. However, if we have a function of the form:

    void f(List balls);

    And if we invoke that function from many different places, each of which creates their own LinkedList to pass into it, then we can't really claim to be hiding the type of the list from anyone but f. And what good is hiding it from one function when everyone else knows it?

    Fortunately, there are several design patterns that address this issue, and allow us to hide the type of an object even from those who seek to create it. These patterns are known asFactories.

    Static Factory

    Consider why we would choose a LinkedList over anArrayList. LinkedLists have fast insert times, but slow indexed access times. For example, you can quickly insert or delete an element of a linked list in O(1) time; but it takes O(n) time to find the nth element. The situation for an ArrayList is reversed. Inserts are O(n), while indexed access is O(1). So the reason to choose one over the other depends on what we plan to do with the list.

    In some sense, the names of the two lists are unfortunate. They might have been better named InsertionList andIndexedAccessList. These two names decouple the reason that the two lists exist from their implementation style. We can enforce that decoupling by creating a class namedListFactory that passes the following test:

     public class StaticListFactoryTest extends TestCase { public void testMakeLists() throws Exception { assertTrue(StaticListFactory.makeInsertionList() instanceof LinkedList); assertTrue(StaticListFactory.makeIndexedAccessList() instanceof ArrayList); } }

    This test can be made to pass by creating aStaticListFactory with the following implementation.

     public class StaticListFactory { public static List makeInsertionList() { return new LinkedList(); } public static List makeIndexedAccessList() { return new ArrayList(); } }

    Now our application can create lists of either form without having to know the detailed implementation type of the list.

    Abstract Factory

    But the DIP has not really been satisfied. Anyone who usesStaticListFactory still depends on concrete functions. They also depend on StaticListFactory, which is the most concrete kind of concrete class--a static class. So the information about type has not been completely hidden.

    For example, let's say that some portion of our application needs to create lists that are synchronized. We could addmakeSynchronizedInsertionList andmakeSynchronizedIndexedAccessList methods to theStaticListFactory class; but this is just pollutes that class with more methods. It might be better to create another static class named StaticSynchronizedListFactory that has the following implementation:

     public class StaticSynchronizedListFactory { public static List makeInsertionList() { return Collections.synchronizedList(new LinkedList()); } public static List makeIndexedAccessList() { return Collections.synchronizedList(new ArrayList()); } }

    In both cases, however, the problem is simply moved. The creator must know whether the list to be created is synchronized or not. In many cases, this is too much knowledge for the creator to have to know. We can solve this problem by using the Strategypattern (see The Strategy, Template Method, and Bridge Patterns).

    Figure 1

    By creating an interface named AbstractListFactory, and giving it two different implementations, we can pass an instance of this factory to whomever needs to create a list, and they won't know what kind of list they are creating.

    The following test describes the way this behaves.

     public class AbstractListFactoryTest extends TestCase { private AbstractListFactory factory; public void testCreateNormal() throws Exception { factory = new NormalListFactory(); assertTrue(factory.makeInsertionList() instanceof LinkedList); assertTrue(factory.makeIndexedAccessList() instanceof ArrayList); } public void testCreateSynchronized() throws Exception { factory = new SynchronizedListFactory(); Class llc = Collections.synchronizedList(new LinkedList()).getClass(); Class alc = Collections.synchronizedList(new ArrayList()).getClass(); assertEquals(llc, factory.makeInsertionList().getClass()); assertEquals(alc, factory.makeIndexedAccessList().getClass()); } }

    The following code passes this test.

     public interface AbstractListFactory { List makeInsertionList(); List makeIndexedAccessList(); } public class NormalListFactory implements AbstractListFactory { public List makeInsertionList() { return new LinkedList(); } public List makeIndexedAccessList() { return new ArrayList(); } } public class SynchronizedListFactory implements AbstractListFactory { public List makeInsertionList() { return Collections.synchronizedList(new LinkedList()); } public List makeIndexedAccessList() { return Collections.synchronizedList(new ArrayList()); } }

    Notice that we have just moved the problem again. While the creators of the lists no longer need to know what kind of lists they are creating; someone must create the factory. Fortunately, every program has a place where this factory can be created: main(). In most cases, the mainfunction is perfectly suited to creating the various factories. These factories are then passed into the rest of the system, which uses them to create the objects they need.

    Problems with Abstract Factory

    One of the most significant problems with this pattern is that the abstract factory interface is volatile. For example, let's say that we want a new method in the factory namedmakeIterableList, which creates the type of list that can be iterated over the fastest. The change to theAbstractListFactory class implies that every class that uses AbstractListFactory must be recompiled and redeployed. This is annoying, especially since most of those classes won't be using the new method.

    To avoid this problem we can change the signature of the interface to be dynamic, as shown by the following test:

     public class DynamicListFactoryTest extends TestCase { private DynamicListFactory factory; public void testCreate() throws Exception { factory = new NormalDynamicListFactory(); assertTrue(factory.make("InsertionList") instanceof LinkedList); assertTrue(factory.make("IndexedAccessList") instanceof ArrayList); assertNull(factory.make("nonsense")); } }

    By passing a string into the make method in order to identify the type of the list we want, we completely obviate the need to ever change the interface ofDynamicListFactory again. All we need to do is change the implementation of NormalDynamicListFactory to handle the new types of lists.

    The following code passes the above test:

     public interface DynamicListFactory { List make(String listType);} public class NormalDynamicListFactory implements DynamicListFactory { public List make(String listType) { if (listType.equals("InsertionList")) return new LinkedList(); else if (listType.equals("IndexedAccessList")) return new ArrayList(); else return null; } }

    Code like this ought to make your hackles rise. Code like this is not type safe! On the other hand, code like this eliminates unnecessary recompiles and redeployments for volatile factories. Which of these two is more important depends on the project, and is a matter of some debate.

    Indeed, there are whole languages that use this approach to typing. They are known as dynamically typed languages. Among their number are languages like Smalltalk, Python, and Ruby. These languages check types at runtime, just likeNormalDynamicListFactory does, as opposed to checking them at compile time. This makes programs in these languages much easier to write, much smaller, and much more flexible. It also eliminates all of the type checks that the compiler could do, and so feels very risky. Such languages make us fear that there will be an inordinate number of runtime errors.

    I won't debate the issue in this column. However, I would ask you to ponder whether a programming team that made use of thorough unit testing of the kind I've been showing here needs to fear runtime errors in dynamically typed language or not.

    Factory Method

    There is one more factory pattern to consider. Recall from my previous column that Strategy and Template Methodwere related patterns--that they solved the same problem in different ways. Since Abstract Factory is justStrategy used for creating objects, there ought to be a factory pattern that uses Template Method instead. There is, and it's called the Factory Method pattern.

    Figure 2

    In the Factory Method pattern, we add abstractmake methods to the class that needs to create the instances of the objects. Then, in derivatives of that class, we implement those make methods appropriately.

    I find I don't use this pattern very often. Making objects is not usually the purview of just a single class. Usually, if an object needs to be made, it needs to be made by many different classes. So Abstract Factory is usually a better choice.

    Factory Overuse

    Factories are cool. Developers who see them for the first time often want to make use of them right away. They may litter their designs with factories. This is almost certainly a mistake.

    Factories are useful when you need to separate the entities that create objects from the type of objects being created. They are useful for satisfying the DIP, when the DIP violation is causing you pain. On the other hand, factories can be a pain in the butt. After all, what could be simpler than new LinkedList()? So take care not to leap into factories without good reason. Don't use them by default, and don't start using them at the first hint that they might be useful. Wait until you have a concrete problem that factories will solve. And then, don't hesitate to use them.