The generic structure of the Service Factory pattern relies on a single common interface that represents multiple service implementations and a directory that contains references and descriptions of the service implementations. The responsibility of the service factory is to select one of the service implementations and return a working implementation that adheres to the application's common interface. Figure 15-1 illustrates the components and relationships between the components in the service factory structure.
The number of service implementations can vary between one and any number of implementations. In fact, you could use the ServiceFactory instance to make the Application instance believe there is a single service implementation when in fact there is an infinite number from which to choose. Further, there is no reason to limit the number of directories to consider in the ServiceFactory instance to one. Instead, the ServiceFactory instance could search many different directories for all possible services to consider.
The core of the Service Factory pattern lies in the ServiceFactory component, rather than in the responsibilities of the remaining components. Further, by now you should be an expert in the responsibilities of the other components. The following are the components in the Service Factory pattern:
Application: The Application component is used only loosely in the context of this pattern. In fact, it is highly likely that the Application component in the Service Factory pattern is actually a component and not a full, stand-alone application. The Application component contains business logic that leverages an external Web Service. The application code relies on a Service interface, but it does not depend on the interface being fulfilled by a specific Web Service. Rather, the Application instance delegates the choice of the Web Service that implements the Service interface to the ServiceFactory component.
ServiceFactory: The ServiceFactory component locates service implementations that fit particular decision criteria that specify the Web Service choice must implement the Service interface. In the event that the factory locates more than one service implementation (such as ServiceImplA and ServiceImplB ), the ServiceFactory component applies an algorithm to choose from the possible service implementations. The ServiceFactory component returns an architecture adapter that supports the Service interface to the Application instance that requested the service implementation.
Service: All potential Web Service targets for the ServiceFactory component support this Service interface. For Web Services to succeed in interbusiness scenarios, there has to be a considerable amount of standardization and cross-business cooperation to determine these common interfaces and gather industry momentum behind the standard interface.
ServiceImplA and ServiceImplB: These are implementations of the Service interface from different vendors . Each of these service implementations is a valid target of the ServiceFactory component; however, each may have different detailed information that would allow the ServiceFactory to prioritize its use. For example, one service implementation may have only 1,000 pounds of raw coffee beans available, and the other implementation may have 10,000 pounds of raw coffee beans for sale.
Directory: This contains references to the service implementations (such as ServiceImplA and ServiceImplB ) that an application may attempt to locate. The directory typically contains a generalized query interface that can look up a service by a particular interface that the implementations support, such as the Service interface.
It is important to remember that the Application component really relies on only two other components, the ServiceFactory component and the Service interface. The ServiceFactory component facilitates the manipulation of the Directory component and the decision between ServiceImplA and ServiceImplB being returned to the Application . It is critical that no code in the Application code path relies on a specific implementation being chosen .
The essential collaborations in the Service Factory pattern revolve around the Application, ServiceFactory , and Directory components. These components have important transitions that combine to implement the pattern. The remaining components, the Service component, and the service implementations are prerequisites to the pattern, but they do not contain logic that relates to the pattern implementation itself.
The sequence of collaborations typically starts with an Application component needing a service to fulfill a part of its algorithm, such as placing an order with a supplier for raw coffee beans. Rather than calling a service directly, the Application component defers the decision on which service to use to a ServiceFactory component. The application could supply specific criteria to the factory, such as that it needs a supplier with 5,000 pounds of coffee beans of a particular type.
Once the ServiceFactory component receives the request, it queries a Directory component for services and defers as much of the search criteria to the directory implementation as possible. Once the directory returns the service implementations that can fulfill your needs, custom logic within the ServiceFactory should decide what service implementation to return to the application. The factory could use the first service in the group returned for the directory, or it could be more sophisticated in its selection criteria. The factory could even evolve to the point of implementing a policy pattern. Figure 15-2 illustrates the sequence in terms of operations against each of the components.
You can read more about policy patterns in San Francisco Design Patterns: Blueprints for Business Software (Addison-Wesley, 2000).
In a service-oriented architecture, the factory is often ignorant of whether it is constructing a service or simply binding to an existing service. I chose to illustrate Figure 15-2 as a construction operation simply because when you move to the Web Service environment, you will construct a local architecture adapter that then facilitates communication with the actual service on the network.