This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies.
You have classes that have dependencies on services whose concrete type is specified at design time. In this example, ClassA has dependencies on ServiceA and ServiceB. Figure 1 illustrates this.
This situation has the following constraints:
- To replace or update the dependencies, you must change your class source code.
- The concrete implementation of the dependencies must be available at compile time.
- Your classes are difficult to test in isolation because they have a direct reference to their dependencies. Therefore, the dependencies cannot be replaced with stubs or mocks.
- Your classes contain repetitive code for creating, locating, and managing their dependencies.
- You want to decouple your classes from their dependencies so that the dependencies can be replaced or updated with minimal or no changes to the source code of your classes.
- You want to write classes that depend on classes whose concrete implementation is not known at compile time.
- You want to be able to test your classes in isolation, without using the dependencies.
- You want to decouple your classes from being responsible for locating and managing the lifetime of dependencies.
Create a service locator that contains references to the services and that encapsulates the logic to locate them. In your classes, use the service locator to obtain service instances. Figure 2 illustrates this.
The service locator does not instantiate the services. It provides a way to register services and it holds references to the services. After the service is registered, the service locator can find the service.
|Note: The service locator should provide a way to locate a service without specifying the concrete type. For example, it could use a string key or a service interface type.|
The Service Locator pattern can be implemented in several ways. For example, the service locator can be a singleton global instance that holds references to services.
In the Composite Web Application Block, composition containers contain a Services collection to hold references to services. Modules use this collection to register and locate services. For more information about how services are located in the Composite Web Application Block, see the section “Locating Services” in the Services topic.
The Service Locator pattern has the following liabilities
- There are more solution elements to manage.
- You have to write additional code to add service references to the locator before your objects can use it.
- Your classes have an extra dependency on the service locator.
- The source code has added complexity; this makes the source code more difficult to understand.
- Dependency Injection. The Dependency Injection pattern solves the same problems that the Service Locator pattern solves, but it uses a different approach.
- Inversion of Control. The Service Locator pattern is a specialized version of the Inversion of Control pattern.