El patrón de localización de servicios es un patrón de diseño utilizado en el desarrollo de software para encapsular los procesos involucrados en la obtención de un servicio con una fuerte capa de abstracción. Este patrón utiliza un registro central conocido como “localizador de servicios” que, a pedido, devuelve la información necesaria para realizar una determinada tarea.
El ServiceLocator es responsable de devolver instancias de servicios cuando los consumidores o los clientes del servicio los solicitan.
Patrón de localizador de servicio de diagrama UML
Componentes de diseño
- Localizador de servicios: el localizador de servicios abstrae los servicios de búsqueda de API, las dependencias de proveedores, las complejidades de búsqueda y la creación de objetos comerciales, y proporciona una interfaz simple para los clientes. Esto reduce la complejidad del cliente. Además, el mismo cliente u otros clientes pueden reutilizar el Localizador de servicios.
- InitialContext: el objeto InitialContext es el punto de inicio en el proceso de búsqueda y creación. Los proveedores de servicios proporcionan el objeto de contexto, que varía según el tipo de objeto comercial proporcionado por el servicio de búsqueda y creación del localizador de servicios.
- ServiceFactory: el objeto ServiceFactory representa un objeto que proporciona gestión del ciclo de vida para los objetos BusinessService. El objeto ServiceFactory para beans empresariales es un objeto EJBHome.
- BusinessService: BusinessService es un rol que cumple el servicio al que el cliente desea acceder. ServiceFactory crea, busca o elimina el objeto BusinessService. El objeto BusinessService en el contexto de una aplicación EJB es un bean empresarial.
Supongamos clases con dependencias en servicios cuyos tipos concretos se especifican en tiempo de compilación.
En el diagrama anterior, ClassA tiene dependencias de tiempo de compilación en ServiceA y ServiceB. Pero esta situación tiene inconvenientes.
- Si queremos reemplazar o actualizar las dependencias, debemos cambiar el código fuente de las clases y volver a compilar la solución.
- La implementación concreta de las dependencias debe estar disponible en tiempo de compilación.
Mediante el uso del patrón del localizador de servicios:
En palabras simples, el patrón del localizador de servicios no describe cómo instanciar los servicios. Describe una forma de registrar servicios y localizarlos.
Veamos un ejemplo de patrón de localizador de servicios.
// Java program to // illustrate Service Design Service // Locator Pattern import java.util.ArrayList; import java.util.List; // Service interface // for getting name and // Executing it. interface Service { public String getName(); public void execute(); } // Service one implementing Locator class ServiceOne implements Service { public void execute() { System.out.println("Executing ServiceOne"); } @Override public String getName() { return "ServiceOne"; } } // Service two implementing Locator class ServiceTwo implements Service { public void execute() { System.out.println("Executing ServiceTwo"); } @Override public String getName() { return "ServiceTwo"; } } // Checking the context // for ServiceOne and ServiceTwo class InitialContext { public Object lookup(String name) { if (name.equalsIgnoreCase("ServiceOne")) { System.out.println("Creating a new ServiceOne object"); return new ServiceOne(); } else if (name.equalsIgnoreCase("ServiceTwo")) { System.out.println("Creating a new ServiceTwo object"); return new ServiceTwo(); } return null; } } class Cache { private List<Service> services; public Cache() { services = new ArrayList<Service>(); } 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); } } } // Locator class class ServiceLocator { private static Cache cache; static { cache = new Cache(); } public static Service getService(String name) { Service service = cache.getService(name); if (service != null) { return service; } InitialContext context = new InitialContext(); Service ServiceOne = (Service)context.lookup(name); cache.addService(ServiceOne); return ServiceOne; } } // Driver class class ServiceLocatorPatternDemo { public static void main(String[] args) { Service service = ServiceLocator.getService("ServiceOne"); service.execute(); service = ServiceLocator.getService("ServiceTwo"); service.execute(); service = ServiceLocator.getService("ServiceOne"); service.execute(); service = ServiceLocator.getService("ServiceTwo"); service.execute(); } }
Producción:
Creating a new ServiceOne object Executing ServiceOne Creating a new ServiceTwo object Executing ServiceTwo Returning cached ServiceOne object Executing ServiceOne Returning cached ServiceTwo object Executing ServiceTwo
ventajas :
- Las aplicaciones pueden optimizarse en tiempo de ejecución agregando y eliminando elementos del localizador de servicios de forma selectiva.
- Grandes secciones de una biblioteca o aplicación se pueden separar por completo. El único vínculo entre ellos se convierte en el registro.
Desventajas:
- El registro hace que el código sea más difícil de mantener (en lugar de usar la inyección de dependencia), porque no queda claro cuándo introducirá un cambio importante.
- El registro oculta las dependencias de clase que provocan errores en tiempo de ejecución en lugar de errores en tiempo de compilación cuando faltan dependencias.
Estrategias
Las siguientes estrategias se utilizan para implementar Service Locator Pattern:
- Estrategia de EJB Service Locator: esta estrategia utiliza el objeto EJBHome para los componentes de bean empresarial y este EJBHome se almacena en caché en ServiceLocator para uso futuro cuando el cliente necesite el objeto de inicio nuevamente.
- Estrategia JMS Queue Service Locator: esta estrategia es aplicable a los requisitos de mensajería punto a punto. Las siguientes son las estrategias de JMS Queue Service Locator Strategy.
- Estrategia JMS Queue Service Locator
- Estrategia JMS Topic Service Locator
- Escriba la estrategia de localizador de servicios marcada: esta estrategia tiene ventajas y desventajas. Reduce la flexibilidad de la búsqueda, que está en la estrategia del localizador de propiedades de servicios, pero agrega la verificación de tipos de pasar una constante al método ServiceLocator.getHome().