The Inversion of Control Pattern

Introduction

A design pattern is a common solution for a common problem that has already been identified and tested. In other words, it’s a guideline that must be adjusted depending on the context, not used in a single, non-changing syntax.

The Inversion of Control Pattern

The term Inversion of Control (IoC) is a computer programming technique wherein the flow of the control of an application is inverted. Rather than a caller deciding how to use an object, in this technique, the object called decides when and how to answer the caller, so the caller is not in charge of controlling the main flow of the application.

This approach makes your code flexible enough to be decoupled. It can be unaware of what is going on in the call stack because the called object doesn't need to make any assumptions about what the caller is doing.

The Dependency Injection pattern is simply a concrete implementation of the IoC. Unfortunately, as Martin Fowler specifies in his book, there is a lot of confusion about these terms, because the common IoC containers available for languages such as Java or .NET are typically identified as IoC containers, but the techniques implemented in your code when you use these frameworks is the Dependency Injection pattern, which is just one of the available concrete implementations for IoC. For example, if you plan to work with a modularized WPF/Silverlight application using a well-known framework such as Prism, you might implement IoC using the Service Locator pattern and not Dependency Injection because you need a global IoC container available for all the modules. Imagine that you have a simple LogWriter concept that is used to write a log message either to a specific database table or to a specified file. You might depict this as shown in Figure 1.

Using the Code

The UML diagram in Figure 1 is pretty clear; there’s an abstract BaseLogger class that exposes a WriteLog message, and two concrete classes that inherit from BaseLogger. These expose the method in two ways: one writes a log message to a database, the other to the file system. The following code shows the wrong way to use one of these concrete loggers— without applying an IoC implementation:

The biggest problem with this approach—not applying an IoC implementation—is that if you want to specify a different log at runtime, you’ll need to rewrite some code. That’s a huge architectural constraint. For example, suppose that you want to get rid of the FileLogger object. That’s not easy. You can’t simply eliminate it, because the application wouldn’t execute any more, or at least, you would need to modify and recompile it for it to continue working.

To solve the problem, the first step is to decouple the existing hierarchy by using an interface instead of the base abstract class, as illustrated in Figure 2. This way, you simply define a contract between a concrete log and its interface. Subsequently, to write a log message to a different location, you just need to render the interface in a specific way.

The code that follows is a refactored version that uses an IoC approach to declare the type of logger to be used at runtime. This approach is still procedural, because it decides which logger to use, but at least it decouples the code, so this is a somewhat more flexible version of the custom writer.

///<spanclass="code-SummaryComment"><summary></span>

At this point, you need something between the application and the logger that can resolve which logger to use at runtime. The following example uses procedural code to do that without using the Dependency Injection or the Service Locator patterns:

Share

About the Author

I spent some time working as a programmer and computer developer for several IT companies. I gained a lot of knowledge and experience in the process, and met some very supportive people in the industry. In May 2000' I joined LBS College for Higher studies.

I enjoyed my studies as much as academic studies can be enjoyed. I feel that I depend my understanding of computers because of them. The LBS College gives his students a high level of studying, but my main problem with it is that its tests are sometimes completely out of sync with the material that is learned, too long and/or too hard, and so students receive low grades and are frustrated. This is especially demotivating considering the fact that studying there is a lot of work.

I have to agree with RichardJMoss, If you don't give a small example of Dependency Injection and/or Service Locator, you won't show the solution to decouple the FileLogger/DatabaseLogger from the main application.Apart from that, a very simple and easy to understand article

Nice article, although I think for those of use who actually want to use the functionality, a brief explanation of actually *how* to do dependency injection would have been most helpful. I felt the article ended too abruptly in this regard.

I think the article sets up quite nicely for describing dependence injection with IoC, but as you get is a one liner in the "Points of Interest" at the end of the document... maybe a small example of how to do dependency injection, or at least a link to another article which describes this functionality if dependency injection is outside the scope of the initial IoC article.