Что это такое
Паттерн Interpreter вычисляет предложения небольшого языка, строя дерево объектов-выражений — каждый узел умеет вычислять себя сам. Числа вычисляются в себя же; узел сложения вычисляет две свои части и складывает их.
Он подходит для небольших языков: фильтров, формул, простых правил. Настоящие языки требуют настоящих инструментов разбора.
Пример: крошечный калькулятор
Вход 3 + 4 - 2 превращается в дерево узлов Number, Add и Subtract. Один вызов interpret() у корня вычисляет всё выражение.
Каждый узел вычисляет себя сам
parse строит дерево слева направо; interpret() обходит его. Поддержка * была бы одним новым классом узла — существующие остаются нетронутыми.
Вывод: PHP-скрипт
<?php
// Каждый узел знает, как вычислить себя.
interface Expression {
public function interpret(): int;
}
class Number implements Expression {
public function __construct(private int $value) {}
public function interpret(): int {
return $this->value;
}
}
class Add implements Expression {
public function __construct(
private Expression $left,
private Expression $right,
) {}
public function interpret(): int {
return $this->left->interpret() + $this->right->interpret();
}
}
class Subtract implements Expression {
public function __construct(
private Expression $left,
private Expression $right,
) {}
public function interpret(): int {
return $this->left->interpret() - $this->right->interpret();
}
}
function parse(string $input): Expression {
$parts = explode(" ", $input);
$expr = new Number((int) $parts[0]);
for ($i = 1; $i < count($parts); $i += 2) {
$number = new Number((int) $parts[$i + 1]);
$expr = $parts[$i] === "+" ? new Add($expr, $number) : new Subtract($expr, $number);
}
return $expr;
}
$input = "3 + 4 - 2";
echo $input, " = ", parse($input)->interpret(), "\n";
Когда его применять
Применяйте, когда пользователи или конфигурации выражают логику на небольшом языке вашей разработки: фильтры поиска, формулы расчёта цен, правила проверки.
Не применяйте, когда «язык» — это три фиксированных варианта (используйте match) или, наоборот, настоящий язык (используйте генератор парсеров или готовый движок).
Плюсы и минусы
Плюсы: грамматика отображается один в один на небольшие классы; новые операции — это новые классы узлов; деревья выражений можно строить, проверять и использовать повторно.
Минусы: с ростом грамматики становится тяжело; разбор всё равно приходится писать самому; производительность скромная по сравнению с скомпилированной логикой.