Factory Pattern
The factory pattern is an object-oriented design pattern in which a component (interface, class, etc. depending on the language) called a "factory"* is defined that is used to and is responsible for creating a particular type of object (or types that inherit from that type) in lieue of creating that type (or subtypes) directly in the code that needs to create it.
*Although it is customary to include "Factory" in the name of a component which serves this role, any object whose primary responsibility is to construct some other object is a "factory" regardless of its naming (and, similarly, an object that contains "Factory" in its name is not necessarily a factory unless it actually is used to construct other objects).
There are several situations that call for a use of a factory, but the underlying principle is that there is some motivation for making the code that needs to construct the object unaware of the details of how it is constructed.
Polymorphism
One reason that one may wish to separate the details of construction from the code that needs to apply that construction is if there are many different subtypes (or configuration options) that the calling code needs to be able to configure. For example, if there are both real and test versions of a class, using a factory rather than creating the real version directly woud allow tests to supply a version of the factory that instantiates the test version in testing code. Similarly, if the code needs to instantiate a user interface widget and there are separate versions for each platform, using a factory would allow the logic that selects which version to use based on the current platform to be isolated to a single location (the factory) rather than duplicated throughout all the various pieces of code that happen to create that widget.
Simplifying Usage
Another reason that one might wish to separate the details of construction from the code that needs to apply construction is to simplify the locations where the object needs to be constructed. For example, if there are many different parameters that must be supplied to the constructor but call sites that create the object only need to vary one or two of the constructor parameters, passing a single factory object to the call site (and storing all the parameters except the one or two that are supplied by the call site as member variables in the factory) makes the call sites simpler (by not having to pass a long list of parameters that aren't needed by the call site except for passing along to the object's constructor).
Limiting Access to Constructor Parameters
Yet another case where one might wish to separate details of construction from code that needs to apply that construction is to more carefully control which code can access all of the details or constructor parameters of the object that is being constructed. For example, suppose that there is code that needs to lazily create a connection to a database and that creating the connection to the database requires the password to the database. Providing the password to every function that may need to talk to the database increases the risk that one of those functions will store or misuse the password other than to create this more limited view of the data in the database. Using a factory, however, allows the various places that need to talk to the database to create this connection without being able to access the password ( which is hidden in the internals of the factory object that actually creates the connection).
There are many, many cases where a factory would not be appropriate, so I won't be able to list all of them. However, the general rule of thumb is the opposite of the principle for using a factory; if a factory is not necessary, don't use it.
Direct Parameters
One reason not to use a factory is if you can supply the object that is needed, directly, rather than supplying a factory that you then use to construct the object. You should only supply the factory if you need to cosntruct multiple instances of the object or if the object needs to be constructed lazily (e.g. the object is expensive to construct, you don't use it in all code paths, and you want to defer construction to the code paths that actually use it). If, however, the calling code can create the object upfront and simply supply it (e.g. there is only one instance used and it doesn't need to be created lazily), then you should simply take the object (not its factory) as a parameter. This still allows the caller to change the details of construction (e.g. to create a test version instead of the real version) but avoids an unnecessary extra layer of indirection.
Simple, Cheap, Non-Polymorphic Objects
Very simple objects that are inexpensive and simple to create (do not need to be lazily created, don't have many constructor parameters) and have only one type (or very few, limited, well-known subtypes) should generally be constructed directly rather than with a factory. For example, creating primitives or other simple objects (2d points, complex numbers, etc.) with a factory is a "code smell". Except in very rare situations in which you want to allow the caller to vary the particular list or map implemention being used (e.g. in a tree datastructure where you want to allow a particular application to choose which list implementation to use for child nodes), using a factory for such simple components would likewise raise eyebrows and is probably inadvisable even though there are multiple implementations.
Java
// FooFactory.java /** * Creates instances of class Foo (in a real example, you * would obviously replace "Foo" both here and below with whatever * class you are actually instantiating with this factory). */ public interface FooFactory { /** * Creates an instance of class Foo. * * <p>Note that, in this paricular example, this function takes no parameters. * In a real example, this method could take parameters, but it varies by * factory. Typically, the factory function takes in fewer parameters * than is actually needed to construct the object (the remaining * parameters are provided in the constructor of the class that implements * this particular factory interface). When creating a factory, you * should limit the parameters to those which vary between call sites; * if all call sites provide the same list of parameters, don't support * any parameters in the factory create function; if call sites * use the same three parameters but vary one other parameter, then * put one parameter here and make the other three into constructor * parameters of the class that implements the Factory interface. * * <p>The name of this function should reflect the fact that it is going * to create an object. While I personally prefer "create", you do not * need to use the same name (though you should be consistent in your * code in your naming of factory functions). Alternatives might include * "newFoo", "instantiate", "allocate", "make", etc. * * <p>Please note that some factories may or may not return null (e.g. * some factories may return null rather than throwing an exception on failure, * while others may always succeed or may always return non-null or throw). You * should be very careful when creating your own factory classes to carefully * document whether your factory function can or cannot return null. If it * can return null, also consider annotating the function @Nullable. * * @return the Foo that was constructed */ Foo create(); }
// FooFactoryImpl.java /** * An illustration of how the factory interface might be implemented. * This naming assumes that there is only one implementation, but there * could, in fact, be multiple factory implementations (if there were * multiple implementations, the name should probably include a modifier * that distinguishes them, for example, "MacFooFactoryImpl", * "LinuxFooFactoryImpl", and "WindowsFooFactoryImpl" if there were * different implementations for different platforms). This example * also assumes that Foo takes two construtor parameters, a * String parameter and an int parameter, in order to illustrate how * factories reduce the number of parameters required to create the object * for the code that uses the factory to instantiate the object. */ final class FooFactoryImpl implements FooFactory { private final String firstParam; private final int secondParam; public FooFactoryImpl(String firstParam, int secondParam) { this.firstParam = firstParam; this.secondParam = secondParam; } @Override public Foo create() { return new Foo(firstParam, secondParam); } }
C++
// foo_factory.h #ifndef __FOO_FACTORY_H__ #define __FOO_FACTORY_H__ // Obviously, replace this with whatever namespace is appropriate // for your project, library, etc. We only use this to teach by example -- // one shouldn't dump code into the global scope but should use an // appropriate namespace, instead. The actual namespace to use, though, // will be dependent on the particular library or project in question. namespace some_namespace { // Forward declaration of the class Foo that is being created. // We could also simply include the corresponding header, but since // the signature only uses a pointer to this class (rather than the) // actual class, we can get away with simply declaring it, which // can help reduce build time by avoiding the need to include the // full declaration of "Foo" where only the factory needs to be referenced. class Foo; /*! * \brief Creates instances of class Foo. * * Note that in a real example, you would obviously replace "Foo" both here * and below with whatever class you are actually instantiating with this. */ class FooFactory { public: // Needed to allow inheriting classes to provide a destructor virtual ~FooFactory(); /*! * \brief Creates an instance of class Foo. * * Note that, in this paricular example, this function takes no parameters. * In a real example, this method could take parameters, but it varies by * factory. Typically, the factory function takes in fewer parameters * than is actually needed to construct the object (the remaining * parameters are provided in the constructor of the class that implements * this particular factory interface). When creating a factory, you * should limit the parameters to those which vary between call sites; * if all call sites provide the same list of parameters, don't support * any parameters in the factory create function; if call sites * use the same three parameters but vary one other parameter, then * put one parameter here and make the other three into constructor * parameters of the class that implements the Factory interface. * * Also note that, when creating your own factory, you should carefully * document whether the function can ever return null (e.g. on failure) * or whether it will always return a non-null result. Also, while * a factory should always return a newly allocated object on each * invocation (in order for it to be applying the factory pattern), you * should be careful in documenting the allocation and ownership of * the returned object (i.e. is it the caller's responsibility to * deallocate the object? Or does the factory deallocate it? In a * standard factory pattern, the caller will be responsible for * deallocating the result using delete, but it is worth * documenting for clarity, as there are similar, related patterns * that may use similar naming but which specify otherwise). * * The name of this function should reflect the fact that it is going * to create an object. While I personally prefer "Create", you do not * need to use the same name (though you should be consistent in your * code in your naming of factory functions). Alternatives might include * "Allocate", "Instantiate", "Make", "NewFoo", etc. * * Please also note that this example makes both the return type * and the factory function, itself, const. However, this will not * necessarily be the case for other factories. While one should make * these const if possible, in many cases you will want a non-const * object as a result instead of a const object. In most cases, the * factory function, itself, should "const"; however, there are some * cases where a factory might be non-const (e.g. if the factory * maintains a tally of the number of objects that were constructed, * for example); however, be aware that a non-const function may be * an indication that the class is actually implementating a related * but different pattern such as the flyweight pattern, rather than * being a factory in the purest sense of the word. * * \return the Foo that was constructed */ virtual const Foo* Create() const = 0; protected: // Not technically needed, because this class contains an unimplemented // virtual method and cannot be constructed, anyway; however, I prefer // specifying this both for parallelism (if the destructor is specified, // I think it is stylistically preferable to also declare a constructor) // and to emphasize the fact that only inheriting classes can create this. FooFactory(); }; } // namespace some_namespace #endif
// foo_factory.cpp #include "foo_factory.h" namespace some_namespace { FooFactory::FooFactory() {} FooFactory::~FooFactory() {} } // namespace some_namespace
// foo_factory_impl.h #ifndef __FOO_FACTORY_IMPL_H__ #define __FOO_FACTORY_IMPL_H__ #include <string> #include "foo_factory.h" namespace some_namespace { /*! * \brief An example implementation of FooFactory. * * The name used in this example assumes that there is only one * implementation (because, otherwise, you would want to include * additional modifiers in the name such as "WindowsFooFactoryImpl", * "MacFooFactoryImpl", "LinuxFooFactoryImpl", etc.). This example * further assumes that the constructor for Foo takes a string * and integer as its parameters (in order to illustrate how factories) * reduce the number of parameters that the caller needs to provide. * * This example also assumes that you are using C++11 (or later). If you * are compiling with an earlier version of C++, simply remove "final" * and "override" from the code that is listed below. */ class FooFactoryImpl final : public FooFactory { public: FooFactoryImpl(const std::string& param1, int param2); virtual ~FooFactoryImpl(); virtual const Foo* Create() const override; private: std::string param1_; int param2_; }; } // namespace some_namespace #endif
// foo_factory_impl.cpp #include "foo_factory_impl.h" #include "foo.h" // <= needed to actually create the object namespace some_namespace { FooFactoryImpl::FooFactoryImpl(const std::string& param1, int param2) : param1_(param1), param2_(param2) {} FooFactoryImpl::~FooFactoryImpl() {} const Foo* FooFactoryImpl::Create() const { return new Foo(param1_, param2_); } } // namespace some_namespace
These are some realistic (but nevertheless made up) examples written to resemble real code that you may encounter in the wild that demonstrate how a factory pattern can be applied in a positive way.
SocketFactory
This example is good in that the factory is needed to lazily construct the object, there are likely going to be many places that need to perform this construction, and the logic for constructing the object is required. Furthermore, real network connections are not easy to deal with in tests, and so using a factory allows for a fake connection to be created. It also reduces the number of places that need to be scrutinized for proper use of encrypted connections.
// Before (without the factory): // This code handles a change in the system state. Some changes in // state require propagating the update to a remote server, while // other state changes are purely local and do not need to be synced. void HandleUpdate( // ... const std::string& host_or_ip, short port_number, EncryptionAlgorithm encryption_algorithm, // ... ) { // ... if (sync_required) { std::unique_ptr<Socket> socket(CreateSocketForSync( host_or_ip, port_number, encryption_algorithm)); // ... do sync ... } // ... }
// After (with the factory): // This code handles a change in the system state. Some changes in // state require propagating the update to a remote server, while // other state changes are purely local and do not need to be synced. void HandleUpdate( // ... const SocketFactory& socket_factory, // ... ) { // ... if (sync_required) { std::unique_ptr<Socket> socket(socket_factory.Create()); // ... do sync ... } // ... }
EnemyFactory
This is a good example, because multiple items need to be created (and thus a factory rather than passing the object directly is necessary) and also because this is a case of polymorphism (where different types of characters need to be created). This also shows some of the efficiency benefits that a factory pattern can provide; without the use of a factory, a switch statement is executed on each iteration of the loop. With a factory, however, the decision between using a SlimeEnemyFactory, OrcEnemyFactory, or DragonEnemyFactory can be made earlier so that, inside the loop, only the object construction is taking place, thereby also speeding up the application.
// Before (without a factory): // Initializes the dungeon "Dead Man's Run", one of many // dungeons in the game. This basically sets up the world // map, adds enemies to the map, and initializes the loot. void InitializeDeadMansRunDungeon( // ... DifficultyLevel difficulty_level, // ... ) { // ... for (int i = 0; i < enemy_locations.size(); i++) { const Coord& location = enemy_locations[i]; switch (difficulty_level) { case EASY: map.AddCharacterAt(new SlimeEnemy, location); break; case MODERATE: map.AddCharacterAt(new OrcEnemy, location); break; case HARD: map.AddCharacterAt(new DragonEnemy, location); break; } } // ... }
// After (with a factory): // Initializes the dungeon "Dead Man's Run", one of many // dungeons in the game. This basically sets up the world // map, adds enemies to the map, and initializes the loot. void InitializeDeadMansRunDungeon( // ... const CharacterFactory& enemy_factory, // ... ) { // ... for (int i = 0; i < enemy_locations.size(); i++) { const Coord& location = enemy_locations[i]; map.AddCharacterAt(enemy_factory.Create(), location); } // ... }
These made up examples should clarify how not to use a factory.
PointFactory
In this example, the factory complicates things unnecessarily, because the factory takes the same parameters as the constructor for the Point object (and therefore isn't simplifying or improving that aspect of the construction) and because Point is simple and non-polymorphic (and therefore isn't providing flexibility in terms of selecting an implementation).
// Bad (using the factory): // Draws a bunch of items on the screen void Draw( // ... const PointFactory& point_factory, // ... Screen* screen) { // ... std::unique_ptr<Point> p1(point_factory->Create(0, 0)); std::unique_ptr<Point> p2(point_factory->Create(5, 5)); screen->DrawLine(*p1, *p2); // ... } // Good (without the factory): // Draws a bunch of items on the screen void Draw( // ... Screen* screen) { // ... Point p1(0, 0); Point p2(5, 5); screen->DrawLine(p1, p2); // ... }
DatabaseConnectionFactory
Although there may be cases where a DatabaseConnectionFactory makes sense, this particular code does not lazily construct the connection and, therefore, it can simply take the connection directly rather than creating it through the factory object. A benefit to doing it in this way (aside from simplifying callers and testing code) is that it also allows callers to potentially reuse the same connection object (rather than having a new one get created each and every time).
// Bad (with a factory) void SaveEmail( const std::string& username const std::string& email_address, const DatabaseConnectionFactory& factory) { std::unique_ptr<DatabaseConnection> db(factory.Create()); db->Insert(/* ... */); } // Good (without a factory) void SaveEmail( const std::string& username const std::string& email_address, DatabaseConnection* db) { db->Insert(/* ... */); }
Curious to see how this design pattern is used in the wild? While we make no claim regarding the "good-ness" or "bad-ness" of these uses, here are a handful of real examples to look at on GitHub that illlustrate this design pattern: