Modèle de localisateur de service

Modèle de localisation de service

1. introduction

Dans ce didacticiel, nous allons en apprendre davantage surthe Service Locator design pattern in Java.

Nous allons décrire le concept, mettre en œuvre un exemple et souligner les avantages et les inconvénients de son utilisation.

2. Comprendre le modèle

The purpose of the Service Locator pattern is to return the service instances on demand. Ceci est utile pour découpler les consommateurs de services des classes concrètes.

Une implémentation comprendra les composants suivants:

  • Client - l'objet client est un consommateur de service. Il est responsable de l'appel de la demande à partir du localisateur de services

  • Service Locator - est un point d'entrée de communication permettant de renvoyer les services à partir du cache.

  • Cache - un objet pour stocker les références de service à réutiliser ultérieurement

  • Initialiseur - crée et enregistre des références aux services dans le cache

  • Service - le composant Service représente les services d'origine ou leur implémentation

L'objet de service d'origine est recherché par le localisateur et renvoyé à la demande.

3. la mise en oeuvre

Maintenant, soyons pratiques et examinons les concepts à travers un exemple.

Tout d'abord, nous allons créer une interfaceMessagingService pour envoyer des messages de différentes manières:

public interface MessagingService {

    String getMessageBody();
    String getServiceName();
}

Ensuite, nous définirons deux implémentations de l'interface ci-dessus, qui envoient des messages par e-mail et SMS:

public class EmailService implements MessagingService {

    public String getMessageBody() {
        return "email message";
    }

    public String getServiceName() {
        return "EmailService";
    }
}

La définition de la classeSMSService est similaire à la classeEmailService.

Après avoir défini les deux services, nous devons définir la logique pour les initialiser:

public class InitialContext {
    public Object lookup(String serviceName) {
        if (serviceName.equalsIgnoreCase("EmailService")) {
            return new EmailService();
        } else if (serviceName.equalsIgnoreCase("SMSService")) {
            return new SMSService();
        }
        return null;
    }
}

Le dernier composant dont nous avons besoin avant de rassembler l'objet de localisateur de service est le cache.

Dans notre exemple, il s'agit d'une classe simple avec une propriétéList:

public class Cache {
    private List services = new ArrayList<>();

    public MessagingService getService(String serviceName) {
        // retrieve from the list
    }

    public void addService(MessagingService newService) {
        // add to the list
    }
}

Enfin, nous pouvons implémenter notre classe de localisateur de services:

public class ServiceLocator {

    private static Cache cache = new Cache();

    public static MessagingService getService(String serviceName) {

        MessagingService service = cache.getService(serviceName);

        if (service != null) {
            return service;
        }

        InitialContext context = new InitialContext();
        MessagingService service1 = (MessagingService) context
          .lookup(serviceName);
        cache.addService(service1);
        return service1;
    }
}

La logique ici est assez simple.

La classe contient une instance desCache. Ensuite, dans la méthodegetService(), elle vérifiera d'abord le cache pour une instance du service.

Ensuite, si c'estnull,, il appellera la logique d'initialisation et ajoutera le nouvel objet au cache.

4. Essai

Voyons comment nous pouvons obtenir des instances maintenant:

MessagingService service
  = ServiceLocator.getService("EmailService");
String email = service.getMessageBody();

MessagingService smsService
  = ServiceLocator.getService("SMSService");
String sms = smsService.getMessageBody();

MessagingService emailService
  = ServiceLocator.getService("EmailService");
String newEmail = emailService.getMessageBody();

The first time we get the EmailService from the ServiceLocator a new instance is created and returned. Ensuite, après l'avoir appelé la prochaine fois, lesEmailService seront renvoyés du cache.

5. Localisateur de services vs injection de dépendances

À première vue, le modèle de localisation de service peut ressembler à un autre modèle bien connu, à savoir, l’injection de dépendance.

Tout d'abord, il est important de noter queboth Dependency Injection and the Service Locator pattern are implementations of the Inversion of Control concept.

Avant d'aller plus loin, apprenez-en plus sur l'injection de dépendances dans cewrite-up.

The key difference here is that the client object still creates its dependencies. Il utilise simplement le localisateur pour cela, ce qui signifie qu'il a besoin d'une référence à l'objet localisateur.

En comparaison, lorsqu’on utilise l’injection de dépendance, les dépendances sont données à la classe. L'injecteur n'est appelé qu'une fois au démarrage pour injecter des dépendances dans la classe.

Enfin, examinons quelques raisons d'éviter d'utiliser le modèle de localisateur de service.

Un argument contre, c’est que cela rend les tests unitaires difficiles. Avec l'injection de dépendance, nous pouvons passer des objets fictifs de la classe dépendante à l'instance testée. D'autre part, il s'agit d'un goulot d'étranglement avec le modèle de localisateur de service.

Un autre problème est qu'il est plus délicat d'utiliser des API basées sur ce modèle. La raison en est que les dépendances sont masquées à l'intérieur de la classe et qu'elles ne sont vérifiées qu'au moment de l'exécution.

Malgré tout, le modèle Service Locator est facile à coder et à comprendre, et peut constituer un excellent choix pour les petites applications.

6. Conclusion

Ce guide explique comment et pourquoi utiliser le modèle de conception Service Locator. Il aborde les principales différences entre le modèle de conception Service Locator et le concept d'injection de dépendance.

En général, il appartient au développeur de choisir comment concevoir les classes dans l’application.

Le modèle Service Locator est un modèle simple permettant de découpler le code. Toutefois, si vous utilisez les classes dans plusieurs applications, l’injection de dépendances est un bon choix.

Comme d'habitude, le code complet est disponible dans lesGithub project.