Accueil / Tutoriels / Command : encapsuler des actions pour mieux les contrôler
Command : encapsuler des actions pour mieux les contrôler
Publié le 16 Juin 2025Command (Commande en français) est un design pattern qui permet d'encapsuler une requête sous forme d'objet, rendant possible sa mise en file, son annulation, sa journalisation ou encore sa réexécution. Ce pattern trouve des applications concrètes dans de nombreuses situations en programmation web, en particulier dans les systèmes complexes nécessitant une séparation claire entre l'émetteur d'une action et son exécution.
Principe du pattern Command
Exemples d’utilisations du pattern Command
Centraliser les actions utilisateurs dans une interface administrateur
Implémenter une file d'attente pour des traitements asynchrones
Points d’attention
Implémenter le pattern Command
Voici un exemple en Go :
package command
// Command définit l'interface que toutes les commandes concrètes doivent implémenter.
type Command interface {
Execute()
}
package command
// Queue CommandQueue gère une file de commandes à exécuter.
type Queue struct {
queue []Command
}
// NewQueue crée et renvoie une nouvelle file de commandes vide.
func NewQueue() *Queue {
return &Queue{
queue: []Command{},
}
}
// AddCommand ajoute une commande dans la file.
func (cq *Queue) AddCommand(cmd Command) {
cq.queue = append(cq.queue, cmd)
}
// Process exécute toutes les commandes en attente et vide ensuite la file.
func (cq *Queue) Process() {
for _, cmd := range cq.queue {
cmd.Execute()
}
cq.queue = []Command{}
}
package command
import "training.go/designpatterns/command/service"
// SendWelcomeEmailCommand encapsule l'action d'envoi d'un e-mail de bienvenue.
type SendWelcomeEmailCommand struct {
emailService *service.EmailService
userEmail string
}
// NewSendWelcomeEmailCommand construit la commande avec son Receiver et l'adresse e-mail du destinataire.
func NewSendWelcomeEmailCommand(emailService *service.EmailService, userEmail string) *SendWelcomeEmailCommand {
return &SendWelcomeEmailCommand{
emailService: emailService,
userEmail: userEmail,
}
}
// Execute délègue au Receiver (EmailService) l'envoi de l'e-mail.
func (c *SendWelcomeEmailCommand) Execute() {
c.emailService.SendWelcomeEmail(c.userEmail)
}
package service
import "fmt"
// EmailService est le Receiver qui connaît la logique métier d'envoi d'e-mail.
type EmailService struct{}
// NewEmailService crée une instance d'EmailService.
func NewEmailService() *EmailService {
return &EmailService{}
}
// SendWelcomeEmail contient la logique concrète pour envoyer l'e-mail de bienvenue.
func (e *EmailService) SendWelcomeEmail(userEmail string) {
fmt.Printf("Welcome email sent to %s\n", userEmail)
}
package main
import (
"designpatterns/command/command"
"designpatterns/command/service"
)
func main() {
emailSvc := service.NewEmailService()
// Création de la commande en lui passant le Receiver et l'adresse e-mail cible.
cmd := command.NewSendWelcomeEmailCommand(emailSvc, "toto@example.com")
// Instanciation de l'Invoker (la file de commandes), ajout et exécution.
queue := command.NewQueue()
queue.AddCommand(cmd)
queue.Process()
}
Le même exemple en PHP :
namespace Practice\DesignPatterns\Command;
interface CommandInterface
{
public function execute(): void;
}
namespace Practice\DesignPatterns\Command;
class CommandQueue {
private array $queue = [];
public function addCommand(CommandInterface $command): void
{
$this->queue[] = $command;
}
public function process(): void
{
foreach ($this->queue as $command) {
$command->execute();
}
$this->queue = [];
}
}
namespace Practice\DesignPatterns\Command;
class EmailService {
public function sendWelcomeEmail(string $user): void
{
echo "Email de bienvenue envoyé à $user\n";
}
}
namespace Practice\DesignPatterns\Command;
class SendWelcomeEmailCommand implements CommandInterface {
private EmailService $emailService;
private string $user;
public function __construct(EmailService $emailService, string $user)
{
$this->emailService = $emailService;
$this->user = $user;
}
public function execute(): void
{
$this->emailService->sendWelcomeEmail($this->user);
}
}
declare(strict_types=1);
use Practice\DesignPatterns\Command\CommandQueue;
use Practice\DesignPatterns\Command\EmailService;
use Practice\DesignPatterns\Command\SendWelcomeEmailCommand;
require "./vendor/autoload.php";
$emailService = new EmailService();
$command = new SendWelcomeEmailCommand($emailService, "toto@example.com");
$queue = new CommandQueue();
$queue->addCommand($command);
$queue->process();