Service Configurator vs. Service Locator
The implementation of ServiceConfigurator in Listing 9 may lead you to think that there is no difference between the ServiceConfigurator class that uses IoC and one that uses the Service Locator
pattern. In fact, you can modify the CustomerService in Listing 8 to use a Service Locator, which will give the CustomerService class either an XMLDataSource or a RelationalDataSource object, based on the Service Locator's internal implementation. By changing the internal implementation of Service Locator, you can switch the DataSource from which CustomerService gets its Customer. In this context, both Service Locator and ServiceConfigurator provide the same functionality to CustomerService. The main difference is how CustomerService gets the DataSource reference. In Service Locator, CustomerService must get the DataSource reference directly from Service Locator, while in ServiceConfigurator, CustomerService gets the DataSource indirectly through ServiceConfigurator.
So, what is the advantage of using Service Locator instead of ServiceConfigurator? ServiceConfigurator frees CustomerService from either acquiring or instantiating the DataSource directly. This makes CustomerService easy to test: simply inject the appropriate DataSource into it. More over, as explained previously in Listing 1 and Listing 2, because you do not make any assumptions about how CustomerService will get the DataSource reference, you can reuse the CustomerService object in different applications. This is the main advantage of using Service Configurator over Service Locator.
What to Inject?
In Figure 5, you see that CustomerService has a relationship with both the DataSource and the Customer classes. Yet this discussion has been about how to inject DataSource into CustomerService. Why not inject Customer into CustomerService? In fact, it is perfectly legitimate to make the ServiceConfigurator inject the Customer object into CustomerService by creating an interface for Customer and referencing it in CustomerService. It all depends on your application requirements and how you want to design the CustomerService class. The previous example made DataSource responsible for creating and storing the Customer object and created a tight coupling between DataSource and Customer. In the future, any change in the Customer class will require changes to all of the implementations of DataSource. However, the design decision was made with the assumption that the public methods of Customer would not undergo any changes, and if any changes occurred in the internals of Customer, then they will not affect the DataSource.
The only anticipated change is how the Customer data is retrieved and stored. Currently, the Customer data is stored in a relational database or in an XML file. Perhaps in the future, it might be stored in an object database or retrieved via a Web service. In either scenario, you can have new classes retrieve and store Customer data. So, based on these assumptions, the example injects only the DataSource into CustomerService, which is used to retrieve and store Customer data.
Add on to Simple Example
This article discussed the IoC pattern and briefly discussed open source frameworks that use it. It also discussed how you could incorporate the IoC pattern in your existing applications using the ServiceConfigurator example. Though simple, the ServiceConfigurator class supports the IoC pattern and provides all of its benefits. You can modify the ServiceConfigurator to add more features as you need for your applications.