I want to give a fairly simple Delphi example that will expose the dependency injection pattern. No framework, no third-party library will be needed here: just plain Delphi code.
I won’t dig into the different forms of dependency injection. I will explain the idea of the pattern as simply as possible.
Instead of giving you bunch of definitions, I will present you with some code. The need to inject a dependency will come naturally. You’ll see:
IDependency = interface
TDependencyA = class(TInterfacedObject, IDependency)
TDependencyB = class(TInterfacedObject, IDependency)
TConsumer = class
constructor Create(aDependencyClassName: string);
WriteLn('Instance of type TDependencyA');
WriteLn('Instance of type TDependencyB');
constructor TConsumer.Create(aDependencyClassName: string);
if aDependencyClassName = 'TDependencyA' then
else if aDependencyClassName = 'TDependencyB' then
if FDependency <> nil then
It is a good and recommended practice in OOP to decrease coupling as much as possible. This means that each component (class) should avoid knowing implementation details of the other components (classes).
In our example, the
TConsumer class has a dependency of type
IDependency. So far so good, since we are abstracting any implementation specifics by using an
interface (contract). The problem becomes obvious when you take a look at the constructor of
TConsumer.Create is instantiating the concrete classes
TDependencyB depending on the
aDependencyClassName. As you can see, the design is not well decoupled here, because the consumer class (
TConsumer) is hard-coding implementation details about its dependency.
The question is: can we decouple this design even more? Yes, the dependency injection pattern will do it for us.
It’s now time to refactor our code a little bit. We’ll start by changing the signature of the constructor of the
constructor TConsumer.Create(aDependency: IDependency);
Instead of choosing the concrete dependency to instantiate within the constructor, we are now injecting the dependency through the
aDependency parameter. Now the class
TConsumer is completely independent of the dependency concrete class.
OK, OK, but we still need to create the concrete dependency instance somewhere, right? Yes, we do. For that, we will create a new class
TDependencyInjector whose only purpose is to return the right dependency instance. This class will use reflection in order to create the right instance of
IDependency. It will use just a
string parameter that contains the dependency class name.
TDependencyInjector = class
class function GetDependency(aDependencyClassName: string): IDependency;
class function TDependencyInjector.GetDependency(aDependencyClassName: string): IDependency;
RttiType := RttiContext.FindType(aDependencyClassName) as TRttiInstanceType;
if RttiType <> nil then
Result:= RttiType.GetMethod('Create').Invoke(RttiType.MetaclassType, ).AsInterface as IDependency;
Finally, let's put all the pieces together. Consider this console application that puts all the pieces in place:
In the code above, we get the
Dependency instance at runtime by using the
TDependencyInjector class. Then, we inject that dependency using the constructor of the class
TConsumer. We have got a more decoupled design by using dependency injection. Don't you agree? ;-)
Get the full source code of this example here (written in Delphi XE 2).