Service Locator Pattern en Java-implementatie

1. Inleiding

In deze tutorial gaan we meer leren over het Service Locator-ontwerppatroon in Java.

We beschrijven het concept, implementeren een voorbeeld en belichten de voor- en nadelen van het gebruik ervan.

2. Het patroon begrijpen

Het doel van het Service Locator-patroon is om de service-instances op aanvraag te retourneren. Dit is handig voor het ontkoppelen van servicegebruikers van concrete klassen.

Een implementatie zal bestaan ​​uit de volgende componenten:

  • Client - het clientobject is een serviceconsument. Het is verantwoordelijk voor het inroepen van het verzoek van de servicelocator
  • Service Locator - is een communicatie-ingangspunt voor het retourneren van services vanuit de cache
  • Cache - een object voor het opslaan van serviceverwijzingen om ze later opnieuw te gebruiken
  • Initializer - maakt en registreert verwijzingen naar services in de cache
  • Service - de servicecomponent vertegenwoordigt de oorspronkelijke services of hun implementatie

Het originele service-object wordt opgezocht door de locator en op verzoek geretourneerd.

3. Implementatie

Laten we nu praktisch worden en de concepten eens bekijken aan de hand van een voorbeeld.

Eerst maken we een MessagingService interface voor het verzenden van berichten op verschillende manieren:

openbare interface MessagingService {String getMessageBody (); String getServiceName (); }

Vervolgens zullen we twee implementaties van de bovenstaande interface definiëren, die berichten verzenden via e-mail en sms:

openbare klasse EmailService implementeert MessagingService {openbare String getMessageBody () {retourneer "e-mailbericht"; } public String getServiceName () {retourneer "EmailService"; }}

De SMS-service class-definitie is vergelijkbaar met de E-mailservice klasse.

Nadat we de twee services hebben gedefinieerd, moeten we de logica definiëren om ze te initialiseren:

openbare klasse InitialContext {opzoeken van openbare objecten (String serviceName) {if (serviceName.equalsIgnoreCase ("EmailService")) {retourneer nieuwe EmailService (); } else if (serviceName.equalsIgnoreCase ("SMSService")) {retourneer nieuwe SMSService (); } retourneer null; }}

Het laatste onderdeel dat we nodig hebben voordat we het service locator-object samenvoegen, is de cache.

In ons voorbeeld is dit een eenvoudige klasse met een Lijst eigendom:

openbare klasse Cache {privélijstservices = nieuwe ArrayList (); public MessagingService getService (String serviceName) {// ophalen uit de lijst} public void addService (MessagingService newService) {// toevoegen aan de lijst}} 

Ten slotte kunnen we onze servicelocatorklasse implementeren:

openbare klasse ServiceLocator {privé statische cache cache = nieuwe cache (); openbare statische MessagingService getService (String servicenaam) {MessagingService-service = cache.getService (servicenaam); if (service! = null) {retourservice; } InitialContext context = nieuwe InitialContext (); MessagingService service1 = (MessagingService) context .lookup (servicenaam); cache.addService (service1); retourservice1; }}

De logica hier is vrij eenvoudig.

De klasse heeft een instantie van de Cache. Vervolgens in de getService () methode, zal het eerst de cache controleren op een instantie van de service.

Als dat dan is nul, het zal de initialisatielogica aanroepen en het nieuwe object aan de cache toevoegen.

4. Testen

Laten we eens kijken hoe we nu instanties kunnen verkrijgen:

MessagingService service = ServiceLocator.getService ("EmailService"); String e-mail = service.getMessageBody (); MessagingService smsService = ServiceLocator.getService ("SMSService"); String sms = smsService.getMessageBody (); MessagingService emailService = ServiceLocator.getService ("EmailService"); String newEmail = emailService.getMessageBody ();

De eerste keer dat we het E-mailservice van de ServiceLocator er wordt een nieuw exemplaar gemaakt en geretourneerd. Vervolgens, na het de volgende keer te hebben genoemd, het E-mailservice wordt uit de cache geretourneerd.

5. Servicelocator versus afhankelijkheidsinjectie

Op het eerste gezicht lijkt het Service Locator-patroon op een ander bekend patroon, namelijk Dependency Injection.

Ten eerste is het belangrijk om dat op te merken zowel Dependency Injection als het Service Locator-patroon zijn implementaties van het Inversion of Control-concept.

Voordat u verder gaat, leest u in dit artikel meer over Dependency Injection.

Het belangrijkste verschil hier is dat het clientobject nog steeds zijn afhankelijkheden creëert. Het gebruikt daarvoor alleen de locator, wat betekent dat het een verwijzing naar het locator-object nodig heeft.

Ter vergelijking: bij gebruik van de afhankelijkheidsinjectie krijgt de klasse de afhankelijkheden. De injector wordt bij het opstarten slechts één keer aangeroepen om afhankelijkheden in de klasse te injecteren.

Laten we tot slot een paar redenen overwegen om het gebruik van het Service Locator-patroon te vermijden.

Een argument hiertegen is dat het het testen van eenheden moeilijk maakt. Met afhankelijkheidsinjectie kunnen we nepobjecten van de afhankelijke klasse doorgeven aan de geteste instantie. Aan de andere kant is dit een knelpunt bij het Service Locator-patroon.

Een ander probleem is dat het lastiger is om API's te gebruiken op basis van dit patroon. De reden hiervoor is dat de afhankelijkheden verborgen zijn in de klasse en dat ze alleen tijdens runtime worden geverifieerd.

Ondanks dit alles is het Service Locator-patroon gemakkelijk te coderen en te begrijpen, en kan het een uitstekende keuze zijn voor kleine toepassingen.

6. Conclusie

Deze handleiding laat zien hoe en waarom u het ontwerppatroon van de Service Locator gebruikt. Het bespreekt de belangrijkste verschillen tussen het Service Locator-ontwerppatroon en het Dependency Injection-concept.

Over het algemeen is het aan de ontwikkelaar om te kiezen hoe de lessen in de applicatie worden ontworpen.

Service Locator-patroon is een eenvoudig patroon om de code te ontkoppelen. In het geval dat de klassen echter in meerdere toepassingen worden gebruikt, is afhankelijkheidsinjectie een juiste keuze.

Zoals gewoonlijk is de volledige code beschikbaar in het Github-project.