Cascading Abstract Factories to Eliminate Dependencies
by Zoran Horvat @zoranh75
When talking about abstract factories, it all begins with this definition:
"Provide an interface for creating families of related or dependent objects without specifying their concrete classes."
[Gama et al., Design Patterns: Elements of Reusable Object-Oriented Software]
In this pattern central object is the client. It is the client's needs that are
targeted by the pattern implementation. Primary goal of the abstract factory is
to cut the client loose from its concrete dependencies that cannot be
instantiated and provided to the client when it is initialized. Client can
instantiate a class without knowing which concrete constructor to use.
Each concrete implementation of the factory provides access to constructor of
one concrete product class. That is how the client can access constructors of
classes that are potentially not known at compile time.
This is the basic setup for the abstract factory pattern. But there is the
downside. Instead of having just the client and one or two concrete
dependencies, we have ended up with seven distinct classes. Added complexity is
the greatest enemy of abstract factories. In many cases this doesn't sound like
a fair trade to developers.
However, in this article, I plan to give you one slightly different reason to
use abstract factories and to accept the added complexity that they incur. As
the result, complexity will actually be moved out of the client and into a
specialized class which is, by pure coincidence, going to be the concrete
Take a look at the following class diagram.
Class A instantiates class B at some point during execution of one of its
methods. Class B in turn instantiates class C, which further instantiates class
D. This object graph is not complicated. It is only four objects deep and it's
relatively easy to understand how it works.
But now the situation begins to complicate. Suppose that the inner-most class D
has two dependencies:
If these two dependencies are mandatory, then we would usually inject them
through class D’s constructor. But now class C is in troubles because it must
also know about these two dependencies. Therefore, class C will also receive
both dependencies through its constructor. So will the class B and, ultimately,
class A. This is what we get in the end:
Net result is that these two dependencies have suddenly become mandatory
dependencies all the classes in the graph. Dependencies of inner objects
propagate upwards all the way to the application root.
Let's continue and see what happens if other classes have dependencies of their
Class C receives another pair of dependencies. Class B adds one dependency of
its own, and so does the class A.
We have reached a forest of dependencies. Class A pulls six dependencies, class
B five, class C four and only class D remains with two of its dependencies
alone. This class diagram indicates that dependencies have flooded over into
classes that own target objects. Not only that classes A, B and C are
needlessly complicated, but they also possess quite a lot of knowledge about
implementation of classes down the stream. If class D is modified, so that it
doesn’t depend on one of its current dependencies, all other classes will have
to be modified as well. That is one notoriously bad consequence.
Simplifying the Design
So what can we do to make the design presented above better? One technique that
I normally use is to avoid instantiating classes directly, but instead to
delegate that operation to concrete factories. Here is the modified design:
Let's start with the class A. Instead of instantiating class B directly, it
will call the factory method to create and return an instance. Right now, class
A has two dependencies, just like I wanted it to have. The only change is that
this time it references factory of B rather than the class B itself.
Immediate result of this change is that now the B factory carries leaked
dependencies. Class A is not dependent on these five dependency classes any
more. B factory lets class A instantiate class B as before. Only this time,
dependencies of B will be supplied by the concrete factory, rather than the
This is the fundamental shift in the design, and this is the mechanism how
abstract factory helps us contain proliferation of the dependencies. Nothing
stops us from applying this mechanism further down the stream. After C factory
has been introduced, class B only depends on that factory and its own natural
dependency. Same goes with class C after D factory has been introduced.
Look at the class diagram once again and see how neatly the dependencies are
isolated now. Each of the classes only depends on its actual dependencies and
on the factory which can be used to create the next instance in the object
Can you believe that these classes are doing precisely the same thing as those
before? Class dependencies are now clearly separated. Class which instantiates
another class does not require dependencies of that other class. Dependencies
are safely stored in concrete factories. Observe this detail. Concrete factory
keeps the dependencies. Abstract factory has nothing to do with the
Not let me reflect on what I said earlier. Dependencies are implementation
leaks. They tell us how the class implements its responsibility. Now how does
this leak fit into the concrete factory? Well, concrete factory goes hand by
hand with its concrete product. Therefore, it is a kind of normal for concrete
product implementation to leak into the concrete factory. It would be a bad
idea if implementation leaked into the abstract factory, or into other classes.
But this way, I believe that classes are much better organized and easier to
implement. Change in implementation of one class only affects its concrete
factory and nothing else. Of course, Inversion of Control (IoC) container may
be affected. But I consider IoC container to be the infrastructure, not
implementation of the application. So I don't really care if it will ever
I have to admit that I was cheating a little with previous diagrams. You have
probably noticed that all class diagrams are using concrete factories. This
made class diagrams significantly easier to draw. The real thing is when
factories and their products become abstract. Let me show you that without
cheating, this time on a smaller scale.
In this case, there are only two classes. Class A instantiates class B and
class B has a concrete dependency. The problem with class A here is the same as
before – it becomes dependent on its product’s dependency. The dependency
relation becomes transitive, to name it in mathematical terms. Or, in less
formal terms, dependency becomes contagious.
Class A implementation depends on class B implementation, which indicates that
implementation has leaked out of the class B into its client.
As before, we can prove that with a simple mind experiment. What happens if
class B changes its implementation, so that then it depends on a completely
different class? To support that modification, class A would also have to
replace its dependency with the new one. This proves that implementation
decision has leaked out of the class B and into the class A.
To solve the problem, I want to make class B abstract. This doesn’t necessarily
mean that class B really has to be declared as an abstract class. Interfaces
are the same in this respect. Remember, interfaces in C# are the same as pure
abstract classes, i.e. classes with all methods declared abstract. But, since
abstract classes and interfaces cannot be instantiated, class A now needs a
mediator. That is the abstract factory which produces abstract product B. Here
is the new class diagram:
To make the picture complete, I had to provide a concrete factory. This factory
class depends on its concrete product. But it also depends on its product's
dependency. Without the dependency readily available, factory object wouldn't
be able to instantiate the product.
From this class diagram, class A is now oblivious of the dependency class. The
price that I paid was adding three more types to the system: there are abstract
and concrete factory and the abstract product. Value added is that now class A
does not have to know anything about the dependency class. Dependency remains
with the class B alone. With this implementation, I am free to redesign class
B. I can remove or replace its dependency and class A’s implementation would
remain exactly the same.
This whole benefit might not be of great importance if I only had classes A and
B in the system. But if the system started to grow, as on previous diagrams, if
I had classes C, D and E, all chained together as one another’s dependencies,
then the dependency graph would quickly start to grow beyond comprehension.
That is the situation in which chain of dependencies can be broken by inserting
an abstract factory and its abstract product in place of a concrete product.
In this article, I have demonstrated one alternative application of the
Abstract Factory pattern. Remember, the original pattern suggests that abstract
factory can be used to provide multiple implementations of an interface.
Abstract factory decouples the client from concrete implementation of a class
it requires. It lets us dynamically switch from instantiating one concrete
class to instantiating another concrete class.
Programmers often forget this, so let me tell it. It is not necessary for the
product to have more than one concrete implementation in the application. It is
sufficient to supply fake product in automated tests and we already have two
implementations. So, writing tests is sometimes a sufficient reason to employ
Abstract Factory pattern. But in this article, I have used the abstract factory
for one completely different purpose.
I have already emphasized that in the examples shown here there were no
multiple implementations of concrete classes. I have strictly taken care to
have only one implementation of each product class. Yet, I felt urge to
decouple client classes from product classes. The trick was in the
dependencies. Concrete product dependencies become dependencies of the client.
Abstract factory hides away the fact that concrete product depends on other
classes. Only concrete factory knows this detail, but once again the client
knows nothing about the concrete factory.
And in that way, the circle is broken. Concrete product's dependencies cannot
leak upstream into the client. Dependencies are filled in by the IoC container
and the client is saved from having to deal with them. That is the interesting
application of the Abstract Factory pattern that I wanted to discuss in this
Published: Oct 1, 2014
Zoran is software architect dedicated to clean design and CTO in a growing software company. Since 2014 Zoran is an author at Pluralsight where he is preparing a series of courses on design patterns, writing unit and integration tests and applying methods to improve code design and long-term maintainability.
Follow him on Twitter @zoranh75 to receive updates and links to new articles.
Watch Zoran's video courses at pluralsight.com (requires registration):
Tactical Design Patterns in .NET: Managing Responsibilities
Applying a design pattern to a real-world problem is not as straightforward as literature implicitly tells us. It is a more engaged process. This course gives an insight into tactical decisions we need to make when applying design patterns that have to do with separating and implementing class responsibilities. More... p>
Tactical Design Patterns in .NET: Control Flow
Improve your skills in writing simpler and safer code by applying coding practices and design patterns that are affecting control flow. More...
Improving Testability Through Design
This course tackles the issues of designing a complex application so that it can be covered with high quality tests. More...
Share this article