YouTip LogoYouTip

Service Locator Pattern

## Service Locator Pattern The Service Locator Pattern is used when we want to use JNDI queries to locate various services. Considering the high cost of looking up JNDI for a particular service, the Service Locator pattern makes full use of caching technology. When a service is requested for the first time, the Service Locator looks it up in JNDI and caches the service object. When the same service is requested again, the Service Locator looks it up in its cache, which can significantly improve the performance of the application. Here are the entities of this design pattern. * **Service** - The actual service that processes the request. References to this service can be found in the JNDI server. * **Context / Initial Context** - JNDI Context carries references to the services to be looked up. * **Service Locator** - The Service Locator is a single point of contact to obtain services by looking up and caching services via JNDI. * **Cache** - The cache stores references to services for reuse. * **Client** - The Client is the object that invokes services via the ServiceLocator. * * * ## Summary ### Intent To provide a centralized service access point within an application for obtaining various services or resources. ### Main Problem Solved * Solves the problem of avoiding hardcoded service access logic when an application needs to access various services or resources. ### Use Cases * When an application needs to access multiple external services or resources and wishes to manage these access logics centrally. ### Implementation Approach * **Service Locator Interface**: Defines the method for obtaining a service. * **Service Locator Implementation**: Implements the service locator interface, encapsulating the service lookup and access logic. * **Service Interface**: Defines the interface or contract of the service. * **Concrete Service**: Implements the service interface, providing specific service functionality. ### Key Code * **Service Locator**: Contains the logic to look up and return the requested service instance. * **Service Interface**: Defines an abstract representation of the service. ### Application Examples * **Enterprise Applications**: Applications use the Service Locator to access database services, message queue services, etc. ### Advantages 1. **Decouples Service Access**: Separates the service access logic from the business logic that uses the service. 2. **Centralized Management**: The service access point is centrally managed, making it easier to maintain and extend. 3. **Flexibility**: Easy to add, modify, or replace services. ### Disadvantages * **Performance Issues**: The Service Locator may introduce performance overhead, especially if a lookup is performed for every service request. * **Overuse**: Can lead to misuse of the design pattern, thereby hiding the system structure. ### Usage Recommendations * Consider using the Service Locator pattern when an application needs to access multiple services in a flexible and maintainable way. ### Notes * Avoid over-reliance on the Service Locator, as it may mask the dependencies of the system, making debugging and optimization difficult. ### Main Roles Involved 1. **Service Locator Interface**: * Defines the method for obtaining a service. 2. **Service Locator Implementation**: * Implements the service locator interface, encapsulating the service lookup and access logic. 3. **Service Interface**: * Defines an abstract representation of the service. 4. **Concrete Service**: * Implements the service interface, providing specific service functionality. 5. **Client**: * Uses the Service Locator to access the required service. The Service Locator pattern helps simplify service access logic and improve the flexibility and maintainability of the application by providing a centralized service access point. * * * < ## Implementation We will create _ServiceLocator_, _InitialContext_, _Cache_, _Service_ as various objects representing the entities. _Service1_ and _Service2_ represent concrete services. The _ServiceLocatorPatternDemo_ class here acts as a client and will use _ServiceLocator_ to demonstrate the Service Locator design pattern. ![Image 1: UML diagram of the Service Locator Pattern](#) ## Step 1 Create a service interface Service. ## Service.java public interface Service{public String getName(); public void execute(); } ## Step 2 Create concrete services. ## Service1.java public class Service1 implements Service{public void execute(){System.out.println("Executing Service1"); } @Override public String getName(){return"Service1"; }} ## Service2.java public class Service2 implements Service{public void execute(){System.out.println("Executing Service2"); } @Override public String getName(){return"Service2"; }} ## Step 3 Create InitialContext for JNDI lookup. ## InitialContext.java public class InitialContext{public Object lookup(String jndiName){if(jndiName.equalsIgnoreCase("SERVICE1")){System.out.println("Looking up and creating a new Service1 object"); return new Service1(); }else if(jndiName.equalsIgnoreCase("SERVICE2")){System.out.println("Looking up and creating a new Service2 object"); return new Service2(); }return null; }} ## Step 4 Create a cache Cache. ## Cache.java import java.util.ArrayList; import java.util.List; public class Cache{private Listservices; public Cache(){services = new ArrayList(); }public Service getService(String serviceName){for(Service service : services){if(service.getName().equalsIgnoreCase(serviceName)){System.out.println("Returning cached "+serviceName+" object"); return service; }}return null; }public void addService(Service newService){boolean exists = false; for(Service service : services){if(service.getName().equalsIgnoreCase(newService.getName())){exists = true; }}if(!exists){services.add(newService); }}} ## Step 5 Create the service locator. ## ServiceLocator.java public class ServiceLocator{private static Cache cache; static{cache = new Cache(); }public static Service getService(String jndiName){Service service = cache.getService(jndiName); if(service != null){return service; }InitialContext context = new InitialContext(); Service service1 = (Service)context.lookup(jndiName); cache.addService(service1); return service1; }} ## Step 6 Use _ServiceLocator_ to demonstrate the Service Locator design pattern. ## ServiceLocatorPatternDemo.java public class ServiceLocatorPatternDemo{public static void main(String[]args){Service service = ServiceLocator.getService("Service1"); service.execute(); service = ServiceLocator.getService("Service2"); service.execute(); service = ServiceLocator.getService("Service1"); service.execute(); service = ServiceLocator.getService("Service2"); service.execute(); }} ## Step 7 Execute the program, output result: Looking up and creating a new Service1 objectExecuting Service1Looking up and creating a new Service2 objectExecuting Service2Returning cached Service1 objectExecuting Service1Returning cached Service2 objectExecuting Service2
← Transfer Object PatternIntercepting Filter Pattern β†’