Registry Pattern
- Type : Structurel
- Difficulté : 4/10
- Définition succincte : Le Registry Pattern est un design pattern structurel qui permet de centraliser l'accès global à des objets ou services partagés à travers l'application. Le registre agit comme un conteneur global dans lequel les objets peuvent être ajoutés, récupérés, et supprimés. Cela permet d'éviter la création d'instances multiples de services ou d'objets souvent utilisés, en centralisant leur accès à un seul endroit.
Objectif du Registry Pattern
L'objectif principal du Registry Pattern est de fournir un point d'accès global à des objets partagés à travers l'application, tout en évitant de devoir les instancier à plusieurs endroits. Il permet également de réduire le couplage en centralisant la gestion des objets et services.
Structure du Registry Pattern
- Registry : La classe qui stocke et gère les objets et services.
- Client : Le code ou les classes qui accèdent aux objets ou services à partir du registre.
Implémentation avec Laravel
Imaginons une application Laravel où plusieurs services, comme un service de notification, un service d'envoi d'emails, et un service de paiement, doivent être accessibles à plusieurs endroits dans l'application. Le Registry Pattern permet de centraliser l'accès à ces services via un registre global.
a) Créer la classe Registry
Voici un exemple simple d'un registre qui permet d'ajouter, récupérer et supprimer des objets.
// app/Patterns/Registry.php
namespace App\Patterns;
class Registry
{
private static array $services = [];
// Ajouter un service dans le registre
public static function set(string $key, $service): void
{
self::$services[$key] = $service;
}
// Récupérer un service depuis le registre
public static function get(string $key)
{
if (!isset(self::$services[$key])) {
throw new \InvalidArgumentException("No service found for key {$key}");
}
return self::$services[$key];
}
// Supprimer un service du registre
public static function remove(string $key): void
{
unset(self::$services[$key]);
}
}
b) Enregistrer des services dans le registre
Supposons que nous ayons plusieurs services, tels que EmailService, PaymentService, et NotificationService, que nous voulons centraliser dans le registre.
Exemple de services
// app/Services/EmailService.php
namespace App\Services;
class EmailService
{
public function sendEmail($to, $subject, $message)
{
// Logique d'envoi d'email
return "Email sent to {$to} with subject: {$subject}";
}
}
// app/Services/PaymentService.php
namespace App\Services;
class PaymentService
{
public function processPayment($amount)
{
// Logique de traitement de paiement
return "Processed payment of \${$amount}";
}
}
// app/Services/NotificationService.php
namespace App\Services;
class NotificationService
{
public function sendNotification($user, $message)
{
// Logique d'envoi de notification
return "Notification sent to {$user} with message: {$message}";
}
}
c) Utilisation du Registry Pattern dans une commande CLI
Nous allons maintenant créer une commande CLI pour tester l'enregistrement et l'utilisation des services via le Registry Pattern.
1. Commande TestRegistry
Cette commande enregistre les services dans le registre et les utilise pour exécuter des tâches comme l'envoi d'emails, le traitement de paiements, et l'envoi de notifications.
// app/Console/Commands/TestRegistry.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Patterns\Registry;
use App\Services\EmailService;
use App\Services\PaymentService;
use App\Services\NotificationService;
class TestRegistry extends Command
{
protected $signature = 'registry:test';
protected $description = 'Test the Registry Pattern by registering and using services';
public function handle()
{
// Enregistrer les services dans le registre
Registry::set('email', new EmailService());
Registry::set('payment', new PaymentService());
Registry::set('notification', new NotificationService());
// Utiliser le service email
$emailService = Registry::get('email');
$this->info($emailService->sendEmail('test@example.com', 'Hello', 'This is a test email.'));
// Utiliser le service de paiement
$paymentService = Registry::get('payment');
$this->info($paymentService->processPayment(100));
// Utiliser le service de notification
$notificationService = Registry::get('notification');
$this->info($notificationService->sendNotification('John Doe', 'You have a new message.'));
// Supprimer un service du registre
Registry::remove('email');
}
}
d) Exécution de la commande
Tu peux maintenant exécuter la commande pour voir comment les services sont enregistrés, récupérés, et utilisés via le registre :
php artisan registry:test
Résultat attendu :
Email sent to test@example.com with subject: Hello
Processed payment of $100
Notification sent to John Doe with message: You have a new message.
Avantages du Registry Pattern
- Point d'accès global : Le Registry Pattern fournit un point d'accès centralisé pour les services partagés à travers l'application, ce qui évite de devoir les instancier à plusieurs endroits.
- Simplification du code client : Les services sont stockés et accessibles facilement, ce qui simplifie leur gestion dans le code client.
- Réduction des dépendances : En centralisant les services dans un registre global, tu réduis les dépendances directes dans les parties clientes du code.
Inconvénients du Registry Pattern
- Problème de globalité : Comme le registre centralise les objets au niveau global, cela peut introduire des dépendances globales qui vont à l'encontre des bonnes pratiques de conception comme l'injection de dépendances.
- Difficulté de testabilité : Le registre global peut rendre les tests unitaires plus difficiles à isoler, car il nécessite de manipuler les objets dans un espace global.
- Couplage fort : Le code client peut devenir fortement couplé au registre, ce qui peut rendre l'évolution du système plus complexe.
Conclusion
Le Registry Pattern est un moyen efficace de centraliser l'accès à des services partagés dans une application Laravel. Il fournit un point d'accès global aux services, ce qui simplifie leur gestion et évite leur duplication. Cependant, il introduit des dépendances globales qui peuvent compliquer les tests unitaires et l'évolution du système. Dans certains contextes, ce pattern peut être avantageux, mais il faut l'utiliser avec prudence pour éviter de créer un couplage trop fort et des dépendances globales non nécessaires.