🗣️ El Patrón Interpreter: Hablando tu propio idioma
El Patrón Interpreter (Intérprete), es uno de esos patrones que no se usan todos los días, pero cuando lo necesitas, te salva la vida.
Su objetivo es: dado un lenguaje, definir una representación de su gramática junto con un intérprete que usa esa representación para interpretar sentencias en el lenguaje.
El problema que resuelve es este:
¿Cómo procesas expresiones complejas (como operaciones matemáticas, reglas de negocio o búsquedas) que siguen una estructura gramatical definida, sin volverte loco con parsers manuales?
La respuesta es convertir cada regla gramatical en una clase. Así, construyes un árbol de objetos (Árbol de Sintaxis Abstracta) que representa la frase y lo recorres para obtener el resultado.

🎼 1. Un ejemplo sencillo: La Partitura Musical
Imagina a un músico leyendo una partitura:
- La partitura está escrita en un lenguaje musical (notas, silencios, claves).
- El músico (El Intérprete) conoce las reglas: sabe que una redonda dura 4 tiempos y una negra 1 tiempo.
- Al leer (interpretar) la partitura, convierte esos símbolos en sonidos.
Concepto (Analogía) | Rol en Interpreter | Tarea Principal |
|---|---|---|
Nota Musical (Do, Re, Mi) | Expresión Terminal | Elementos básicos que no se descomponen más. |
Acorde / Compás | Expresión No Terminal | Combinación de otras expresiones (terminales o no). |
🛠️ 2. Los tres pilares del patrón Interpreter
Para montar nuestro propio lenguaje, necesitamos:
1. Expresión Abstracta
- Una interfaz que declara el método
interpretar(). Todas las reglas gramaticales la implementan.
2. Expresión Terminal
- Representa los elementos básicos del lenguaje (como números o variables). Son las “hojas” del árbol.
3. Expresión No Terminal
- Representa reglas compuestas (como una suma, que contiene dos números). Contiene referencias a otras expresiones.
🤔 1. ¿Qué estructura de datos se suele formar al usar el patrón Interpreter?
🧮 3. El ejemplo clásico: Calculadora
Imagina que quieres procesar la cadena "5 + 10 - 2".
Con Interpreter, esto se convierte en un árbol de objetos:
Resta( Suma( Numero(5), Numero(10) ), Numero(2) )
Al llamar a interpretar() en la raíz (Resta), esta llama recursivamente a sus hijos hasta llegar a los números.
🤔 2. ¿Para qué tipo de problemas NO es recomendable este patrón?
✅ 4. ¿Por Qué Usarlo?
- Extensibilidad: Es fácil cambiar y extender la gramática. Añadir una nueva regla (como “Multiplicar”) es solo crear una clase nueva.
- Estructura: Representa la gramática de forma explícita en el código.
❌ 5. Desventaja a Considerar
- Ineficiencia y Complejidad: Si la gramática es muy compleja, acabas con cientos de clases pequeñas. Además, construir y recorrer el árbol puede ser lento comparado con un parser tradicional optimizado.
🤔 3. ¿Qué patrón se suele usar junto con Interpreter para recorrer el árbol generado?
💡 6. Conclusión
El Interpreter es potente para dominios específicos (DSLs). Si necesitas procesar reglas que cambian frecuentemente o permitir que los usuarios escriban “fórmulas” sencillas, este es tu patrón.
🧠 7. Ejemplo Práctico en PHP
Vamos a crear un intérprete para sumar y restar números.
<?php
// 🔹 1. Expresión Abstracta
interface Expresion
{
public function interpretar(): int;
}
// 🔹 2. Expresión Terminal (Número)
class Numero implements Expresion
{
private int $valor;
public function __construct(int $valor)
{
$this->valor = $valor;
}
public function interpretar(): int
{
return $this->valor;
}
}
// 🔹 3. Expresiones No Terminales (Operaciones)
class Sumar implements Expresion
{
private Expresion $izquierda;
private Expresion $derecha;
public function __construct(Expresion $izquierda, Expresion $derecha)
{
$this->izquierda = $izquierda;
$this->derecha = $derecha;
}
public function interpretar(): int
{
return $this->izquierda->interpretar() + $this->derecha->interpretar();
}
}
class Restar implements Expresion
{
private Expresion $izquierda;
private Expresion $derecha;
public function __construct(Expresion $izquierda, Expresion $derecha)
{
$this->izquierda = $izquierda;
$this->derecha = $derecha;
}
public function interpretar(): int
{
return $this->izquierda->interpretar() - $this->derecha->interpretar();
}
}
// 🔹 4. Cliente
// Queremos resolver: (10 + 5) - 3
// Construimos el árbol:
$diez = new Numero(10);
$cinco = new Numero(5);
$tres = new Numero(3);
$suma = new Sumar($diez, $cinco); // (10 + 5)
$resta = new Restar($suma, $tres); // (Resultado de suma) - 3
echo "La expresión es: (10 + 5) - 3" . PHP_EOL;
echo "El resultado es: " . $resta->interpretar() . PHP_EOL;
// 🖥️ Salida:
// La expresión es: (10 + 5) - 3
// El resultado es: 12
EA, ¡saluditos y nos vemos en los bares! 🍻