Accueil / Tutoriels / Interpreter
Interpreter
Publié le 2 Juin 2025Interpreter est un patron de conception comportemental qui permet d’interpréter une langue formelle ou un langage spécifique. Il définit une représentation grammaticale pour un langage, et fournit un interpréteur pour traiter les phrases de ce langage.
Ce design pattern est utile lorsqu’on veut donner à un utilisateur ou à un administrateur la possibilité de décrire dynamiquement des règles, des expressions ou des filtres sans toucher au code source. On le retrouve souvent dans la création de moteurs de règles personnalisés, de langages de requête simplifiés, ou encore dans des systèmes de filtrage avancés.
Principe
Exemples d’utilisations
Moteur de règles dynamiques dans un CMS ou une application e-commerce
Filtres de recherche avancés dans une interface personnalisable (SaaS, CRM, ERP)
Points d’attentions
Complexité en termes de performance
Difficulté de maintenance du code
Risques de sécurité si les expressions ne sont pas validées
Implémenter un Interpreter
Voici un exemple en Go :
package exp
type Context struct {
User map[string]interface{}
}
type Expression interface {
Interpret(ctx Context) bool
}
package exp
type And struct {
Left, Right Expression
}
func (a And) Interpret(ctx Context) bool {
return a.Left.Interpret(ctx) && a.Right.Interpret(ctx)
}
package exp
type Equals struct {
Key string
Value interface{}
}
func (e Equals) Interpret(ctx Context) bool {
val, ok := ctx.User[e.Key]
return ok && val == e.Value
}
package exp
type NotEquals struct {
Key string
Value interface{}
}
func (e NotEquals) Interpret(ctx Context) bool {
val, ok := ctx.User[e.Key]
return ok && val != e.Value
}
package main
import (
"fmt"
"designpatterns/interpreter/exp"
)
func main() {
ctx := exp.Context{User: map[string]interface{}{
"is_company": true,
"country": "BE",
}}
rule := exp.And{
Left: exp.Equals{Key: "is_company", Value: true},
Right: exp.NotEquals{Key: "country", Value: "FR"},
}
if rule.Interpret(ctx) {
fmt.Println("Afficher le champ TVA")
} else {
fmt.Println("Ne pas afficher le champ TVA")
}
}
Le même exemple en PHP :
namespace Practice\DesignPatterns\Interpreter;
interface Expression {
public function interpret(array $context): bool;
}
namespace Practice\DesignPatterns\Interpreter;
class AndExpr implements Expression {
private Expression $left;
private Expression $right;
public function __construct(Expression $left, Expression $right) {
$this->left = $left;
$this->right = $right;
}
public function interpret(array $context): bool {
return $this->left->interpret($context) && $this->right->interpret($context);
}
}
namespace Practice\DesignPatterns\Interpreter;
class Equals implements Expression {
private string $key;
private $value;
public function __construct(string $key, $value) {
$this->key = $key;
$this->value = $value;
}
public function interpret(array $context): bool {
return isset($context[$this->key]) && $context[$this->key] === $this->value;
}
}
namespace Practice\DesignPatterns\Interpreter;
class NotEquals implements Expression {
private string $key;
private $value;
public function __construct(string $key, $value) {
$this->key = $key;
$this->value = $value;
}
public function interpret(array $context): bool {
return isset($context[$this->key]) && $context[$this->key] !== $this->value;
}
}
declare(strict_types=1);
require "./vendor/autoload.php";
use Practice\DesignPatterns\Interpreter\AndExpr;
use Practice\DesignPatterns\Interpreter\Equals;
use Practice\DesignPatterns\Interpreter\NotEquals;
$context = [
'is_company' => true,
'country' => 'BE',
];
$rule = new AndExpr(
new Equals('is_company', true),
new NotEquals('country', 'FR')
);
if ($rule->interpret($context)) {
echo "Afficher le champ TVA";
} else {
echo "Ne pas afficher le champ TVA";
}