Design patterns: Interpreter
L’Interpreter Pattern è un design pattern comportamentale che viene utilizzato per definire la grammatica di un linguaggio semplice e interpretare le sue espressioni. Viene impiegato quando si vuole elaborare un linguaggio di dominio specifico (DSL) o eseguire operazioni complesse tramite espressioni e regole di sintassi predefinite. Questo pattern suddivide le espressioni complesse in sotto-espressioni più semplici e le valuta ricorsivamente.
Punti di Forza
- Facilità nell’Aggiungere Nuove Regole: Consente di aggiungere nuove regole di interpretazione facilmente, mantenendo il codice organizzato e semplice da estendere.
- Modellazione di Linguaggi Personalizzati: Ideale per creare interpreti per linguaggi personalizzati o di dominio specifico (DSL), fornendo una struttura chiara per la definizione di regole sintattiche.
- Suddivisione e Ricorsione: Divide espressioni complesse in sotto-espressioni più semplici, che possono essere valutate ricorsivamente, facilitando l’interpretazione di linguaggi complessi.
- Flessibilità: Le espressioni possono essere rappresentate in modo flessibile come una struttura ad albero, consentendo di gestire espressioni composte o nidificate.
- Manutenibilità: Il pattern consente di separare in modo chiaro le regole grammaticali e sintattiche, rendendo il codice più manutenibile e comprensibile.
Caso d’Uso
Supponiamo di voler interpretare una semplice espressione matematica (ad esempio, somma e sottrazione) e valutarne il risultato.
Codice PHP
// Interfaccia per tutte le espressioni
interface Expression {
public function interpret(array $context);
}
// Espressione per i numeri
class Number implements Expression {
private $number;
public function __construct($number) {
$this->number = $number;
}
public function interpret(array $context) {
return $this->number;
}
}
// Espressione per la somma
class Add implements Expression {
private $leftExpression;
private $rightExpression;
public function __construct(Expression $leftExpression, Expression $rightExpression) {
$this->leftExpression = $leftExpression;
$this->rightExpression = $rightExpression;
}
public function interpret(array $context) {
return $this->leftExpression->interpret($context) + $this->rightExpression->interpret($context);
}
}
// Espressione per la sottrazione
class Subtract implements Expression {
private $leftExpression;
private $rightExpression;
public function __construct(Expression $leftExpression, Expression $rightExpression) {
$this->leftExpression = $leftExpression;
$this->rightExpression = $rightExpression;
}
public function interpret(array $context) {
return $this->leftExpression->interpret($context) - $this->rightExpression->interpret($context);
}
}
// Utilizzo
$expression = new Add(
new Number(5),
new Subtract(new Number(10), new Number(3))
);
$result = $expression->interpret([]);
echo "Risultato: $result\n"; // Output: Risultato: 12
Spiegazione
- Expression è l’interfaccia comune per tutte le espressioni (numeri, somma, sottrazione).
- Number rappresenta un numero semplice (espressione terminale).
- Add e Subtract sono espressioni non terminali che implementano rispettivamente la somma e la sottrazione.
- interpret() viene utilizzato per valutare l’espressione, ricorsivamente chiamando i metodi interpret sulle espressioni figlie.
In questo esempio, l’espressione composta 5 + (10 - 3) viene creata e valutata usando il pattern Interpreter.
Conclusione
L’Interpreter Pattern è utile quando si devono implementare interpreti per linguaggi di dominio specifico o per valutare espressioni complesse. Questo pattern permette di rappresentare e valutare regole grammaticali in modo strutturato e flessibile.