Factories let you do two things:
- Select the type of the created object.
- Create the object.
A SimpleFactory
lets you create objects of different type depending on runtime arguments. Here, both 1. and 2. happen at the same place, namely the Bicycle createBicycle(String type)
method:
class Foo {
void bar(String bicycleTypeName) {
// The next line creates the object.
// The type selection is made when passing the type string to the
// factory. It is easy to create a different object by passing a
// different string.
Bicycle b = SimpleFactory.createBicycle(bicycleTypeName);
[...] // use b
}
}
The Factory
(or AbstractFactory
) pattern separates 2. the object creation from 1. the type selection. When creating the factory, the type of the created object is selected via type of the factory. Then you can pass this factory to other places, which can then create objects.
class Foo {
void bar(Factory bicycleFactory) {
// The next line creates the object.
// The creator of the bicycleFactory has already selected the
// object type. It is hard to create a different object type,
// because this requires a different factory.
Bicycle b = bicycleFactory.createBicycle();
[...] // use b
}
}
Often, you can use both patterns interchangeably. Usually, the SimpleFactory
is easier to use and implement. However, such a factory must know all involved derived types beforehand, which is not always possible.
The SimpleFactory
violates the open-closed principle (software entities (e.g., classes), should be open for extension, but closed for modification):
- The class is not closed, because adding a new bicycle type requires changing the implementation of the
Bicycle createBicycle(String typeName)
method.
- You can say that the class is closed if you forbid adding new types, but then the class is not open.
This can be a problem if you write code that is used by other people. Say you implement a library that (for some reason) needs a bicycle factory. If you go with the SimpleFactory
pattern, users of the library are not able to add new bicycle types. They can not change the createBicycle
method of SimpleFactory
, because it is part of the library. However, if you go with the AbstractFactory
pattern, users of the library can derive from it and pass their custom factories to the library, which creates their custom bicycles.