Factory Method

Intent

Factory Method is a creational design pattern that provides an interface for creating an object, but allow subclasses to alter the type of an object that will be created.

Problem

Imagine that you're creating a logistics management application. The first version of your app can handle only transportation by trucks, so the bulk of your code lives in a Truck class.

After a while, your app becomes so popular that you get tons of requests to include sea transportation as well.

Great news, right?! But how about the code? It looks that most of your code is coupled to the Truck class, and adding Ships could require rewriting the entire codebase.

Solution

The Factory Method pattern suggests replacing direct object creation (using a new operator) with a call to a special "factory" method. The constructor call should be moved inside that method.

// Before:
Truck t = new Truck();

// After:
Transport t = createVehicle(); // return new Truck()

At first glance, such a move may seem pointless. But now you can override the factory method in a subclass and change the class of an object that will be created. Let's see how it works:

class Logistics
    abstract method createVehicle(): Transport

class RoadLogistics
    method createVehicle(): Transport is
        return new Truck()

class SeaLogistics
    method createVehicle(): Transport is
        return new Ship()"

Of course, there's slight limitation—all products must have a common interface (say, Transport). Factory method in a base class should be returning this common interface. Subclasses may return different concrete products as long as these products have a common base class or interface (for example, both Truck and Ship implement the Transport interface).

interface Transport
    method deliver(something, destination)

class Truck implements Transport
    method deliver(something, destination) is
        // Deliver by ground.

class Ship implements Transport
    method deliver(something, destination) is
        // Deliver by sea.

Clients of a factory method don't care about the particular type of a product they receive. They work with all products using a common product interface.

class Logistics
    abstract method createVehicle(): Transport

class SomeClientClass
    someClientMethod(Logistics logistics, package, destination) is
        // This will create some transport...
        Transport t = logistics.createVehicle();
        // ..it doesn't matter which one, since all transports can "deliver"
        t.deliver(package, destination);

Structure

Structure of the Factory Method pattern
  1. Product defines a single interface for all objects that can be produced by the creator and its subclasses.

  2. Concrete Products are the different implementations of the Product interface.

    Concrete Creators will create and return instances of these classes.

  3. Creator defines a factory method that returns the Product type. This method can either be abstract or have some default implementation. In the first case, all Concrete Creators must implement their factory methods.

    Despite the name, in the real world, the product creation is not the main responsibility of a Creator class. Usually, it has some core business logic that works with Products.

    Here's the analogy: a large software development company can have a training department for programmers. But the primary function of the company is still writing code.

  4. Concrete Creators implement or override the base factory method, by creating and returning one of the Concrete Products.

    Note that a factory method doesn't have to create new instances all the time. It can also return existing objects from some cache, etc.

Pseudocode

This example illustrates how Factory Method can be used for creating cross-platform UI elements. The factory method is defined in base UI dialogue class and returns abstract buttons. The dialog subclasses implement the factory method, by returning a particular variation of buttons. The base dialog class uses the results of the factory method to compose an UI window. The dialog works with buttons through their common interface. So whichever type of buttons the factory method returns, the dialog code will remain functional.

Therefore, the Factory Method pattern makes the primary code of a class independent from the concrete classes of products it uses. Factory Method makes subclasses responsible for choosing concrete classes of products that will be created.

// The Factory Method pattern is applicable only when there is a
// products hierarchy.
interface Button is
    method render()
    method onClick(f)

class WindowsButton implements Button is
    method render(a, b) is
        Create and render a Windows looking button.
    method onClick(f) is
        Bind a native OS click event.

class HTMLButton implements Button is
    method render(a, b) is
        Return an HTML representation of a button.
    method onClick(f) is
        Bind a web browser click event.

// Base factory class. Note that the "factory" is merely a role for the class.
// It should have some core business logic which needs different products to
// be created.
class Dialog is
    method renderWindow() is
        Render other window controls.

        Button okButton = createButton();
        okButton.onClick(closeDialog);
        okButton.render();

    // Therefore we extract all product creation code to a special
    // factory method.
    abstract method createButton()

// Concrete factories extend that method to produce different kinds of products.
class WindowsDialog extends Dialog is
    method createButton() is
        return new WindowsButton()

class WebDialog extends Dialog is
    method createButton() is
        return new HTMLButton()

class ClientApplication is
    field dialog: Dialog

    // Application picks a factory type depending on configuration
    // or environment.
    method configure() is
        if (we are in windows environment) then
            dialog = new WindowsDialog()

        if (we are in web environment) then
            dialog = new WebDialog()

    // The client code should work with factories and products through their
    // abstract interfaces. This way it will remain functional even if you add
    // new product types to the program.
    method main() is
        dialog.initialize()
        dialog.render()

Applicability

When you don't know the exact types and dependencies of the objects, your code should work with.

For instance, when your code should support reading and writing data from multiple sources—file system, database or network. All of these sources would have different types, dependencies and initialization code.

Factory method can hide from the rest of client code the implementation details of a product.

You only need to define a new subclass and implement its factory method. Rest of the code should work just fine, as long as new products follow common product interface.

When you want to give users of your library or framework a way to extend its internal components.

A user can easily subclass some particular component. But how would the framework recognize that subclass and work with it instead of a standard component? A user will have to override every single method that creates instances of standard components and change them to create objects of a custom subclass. That is pretty awkward, isn't it?

The better solution would be to not only give a user means to extend particular classes, but also reduce the code that produces components to a single creational method. In other words, to provide the factory methods.

Let's see how it would work. Imagine that you write an app using an open source UI framework. You app must have round buttons, but the framework provides only square ones.

The first thing that you do is implement the RoundButtons class. But now you need to tell the framework to use this class for creating buttons.

To achieve this, you create a subclass FrameworkWithRoundButtons from a base framework class and override its method createButton. This method still returns Button objects in a base class, but your new subclass produces RoundButtons objects.

Now, in your app, you must initialize the framework using FrameworkWithRoundButtons class instead of default one. And that's about it!

When you want to reuse some existing objects, instead of rebuilding new ones.

For example, when you're dealing with large or resource-intensive objects like database connections, etc.

Imagine a code that gets this done. First, you need to determine whether or not the object had been already created, whether it's ready and select it from a pool. If there are none, only then—create a new instance.

You can't perform all of these checks in a constructor since it must return a new object by definition.

Plus, the client code that uses your class doesn't want to know so much implementation details of your class. Therefore, you need to have a single method for encapsulating this logic. That would be a factory method.

How to Implement

  1. Create a common product interface and make all products implementing it. This interface should define methods that make sense for every product.

  2. Add an empty factory method in the creator class. Its signature should return the abstract product type.

  3. Go over the creator code and find all calls to a product constructors. One by one, extract them to the factory method. Put the factory method call in their place.

    You might need to add a parameter to factory method to control which product the factory method should return.

    At this point, the factory method's code may seem pretty ugly. It could have a large switch operator that picks type of a product that will be created. But don't worry, we'll fix it right away.

  4. Now, let's override the factory method in subclasses and move there the appropriate case from the switch operator in the base method.

  5. The control parameter used in the base creator's class can also be used in subclasses.

    For instance, you may have a creator's hierarchy with a base class Mail and classes Air and Ground, plus the product classes: Plane, Bus and Truck. Air matches Plane just fine, but Ground matches both Bus and Truck at the same time. You can create a new subclass to handle both cases, but there's another option. The client code can pass an argument to the factory method of the Ground class to control which product it receives.

  6. If the base factory method has become empty after all moves, you can make it abstract.

Pros and Cons

  • Follows the Open/Closed Principle.
  • Avoids tight coupling between concrete products and code that uses them.
  • Simplifies code after moving all creational code to one place.
  • Simplifies addition of new products into the program.
  • Requires extra subclasses.

Relations with Other Patterns

Implementations in Different Programming Languages

Java

Extra Content

  • If you can't figure out the difference between various factory patterns and concepts, then read our Factory Comparison guide.