When to use it: Factory Method

The GoF book defines the Factory Method pattern in terms of an ICreator interface that defines a virtual function, CreateIProduct().  The virtual function CreateIProduct() returns a base class, IProduct.  So, classes that derive from ICreator implement CreateIProduct() to return a subclass of IProduct.  In other words, a SubclassOfCreator would create a SubclassOfProduct.

Like the Abstract Factory pattern, this enforces object cohesion – the SubclassOfCreator creates only the types that it can work with.  It also allows for extensibility, because the framework is only providing the ICreator and IProduct interfaces.  The client code will derive from ICreator and IProduct, which eliminates the need for client-specific behaviors in the framework’s code.

The Code

So let’s look at what the code for a Factory Method might look like in C++:

class IProduct {
public:
  virtual void DoSomething() = 0;
  virtual void DoSomethingElse() = 0;
  ...
};

class ICreator {
public:
  virtual unique_ptr<Product> CreateIProduct() = 0;
  void PerformOperation();
  ...
};

These two classes are abstract classes and can’t be instantiated.  They must be subclassed, and the various operations must be implemented in the subclasses.  The subclasses look like this:

class ConcreteProduct : public IProduct {
public:
  virtual void DoSomething() { mValue++; }
  virtual void DoSomethingElse() { mValue--; }
protected:
  int mValue;
};

class ConcreteCreator : public ICreator {
public:
  virtual unique_ptr<Product> CreateIProduct() { return unique_ptr<IProduct>(new ConcreteProduct()); }
};

int main() {
...
ConcreteCreator cc;
unique_ptr<IProduct> myProduct = cc.CreateProduct();
myProduct->DoSomething();
...
}

Here we see that ConcreteCreator.CreateIProduct() creates a new ConcreteProduct.  For easy memory management I’m using a std::unique_ptr, but it’s by no means required.  With this scheme, the client lets ConcreteCreator create whatever subclass of IProduct it thinks is best.

When to use it

This technique is valuable when the ConcreteCreator needs to be extended with a coherent object.  For example, some simple racing games like Mario Kart allow the user to choose a car, and the driver that’s shown on the screen is specific to the car.  With the Factory Pattern, there would be an ICar and an IDriver.  ICar would have a method, CreateIDriver().  Each car (MarioCar, LuigiCar, PrincessCar, etc) would implement CreateIDriver to return the corresponding MarioDriver, LuigiDriver, PrincessDriver, and so on.

This could also be useful in other domains, such as extensible image processing software.  Extensible image processing software might allow third party developers to add items in a special menu.  When clicked, the menu item would open a new, extension-specific dialog.  This could be implemented with IExtension and IExtensionDialog interfaces.  Third-party developers would subclass the IExtension interface to initialize the extension and set the menu item text, and then implement CreateIExtensionDialog() so it returns their extension-specific dialog.

Please leave a comment if this has helped you, or if there’s anything else I can do to help you understand when to use the Factory Method!

Leave a Reply

Your email address will not be published. Required fields are marked *