The factory pattern can ease the pain of adding a dependency, because a factory may contain state and, in fact, can encapsulate multiple dependencies (e.g. instead of providing three dependencies, all needed to invoke some object's constructor, you now provide only a single factory object, where the factory contains those three objects that are needed to be provided to the constructor).
To give an example, compare:
void DoIt(const DependencyA& a, const DependencyB& b) {
// NOTE: "x" is a contrived additional variable that we add here to
// justify why we didn't just pass DependencyC directly.
int x = ComputeX();
std::unique_ptr<DependencyC> dependency_c(new DependencyC(a, b, x));
dependency_c->DoStuff();
}
And:
void DoIt(const DependencyCFactory& factory) {
int x = ComputeX();
std::unique_ptr<DependencyC> dependency_c(factory->Create(x));
dependency_c->DoStuff();
}
Note that the second version required fewer dependencies to the method "DoIt". This does not mean that those dependencies aren't need in the entire program (indeed, the program still makes use of DependencyA and DependencyB in the implementaiton of the factory). However, by structuring it this way, that dependency can be isolated to just the factory code, which keeps other code simpler, makes it easier to change the dependencies of DependencyC
(now only the factory, itself, needs to be updated, not every place that instantiates DependencyC
), and can even have certain safety/security benefits (e.g. if DependencyA
and DependencyB
are sensitive such as database passwords or API keys, limiing their usage to the factory reduces the chances of mishandling, compared to cases where you pass these around everywhere that you need to use the databse or API, for example).
In the example given in the book, the reason why having a factory for the Order
would have helped is that it would have reduced the number of places where the constructor is used directly; only the one place that created the factory would need to be modified to store the Customer
as an additional field of the factory; none of the other uses of the factory would need to be modified. By comparison, without the use of the factory, direct uses of the constructor abound, and each one of them must be updated to somehow obtain access to the Customer
object.