Skip to content

Interpreter (Интерпретатор)

Шаблон проектирования "Интерпретатор" (Interpreter) используется для определения грамматики и интерпретации языка. Этот паттерн позволяет создавать интерпретаторы для языков, используя классы, которые представляют грамматические правила. Он особенно полезен, когда необходимо интерпретировать выражения или команды, которые могут быть представлены в виде дерева.

Основные компоненты паттерна "Интерпретатор":

  1. Контекст (Context): класс, который содержит информацию, необходимую для интерпретации выражений.
  2. Абстрактный выражение (Abstract Expression): интерфейс или абстрактный класс, который определяет метод для интерпретации.
  3. Конкретные выражения (Concrete Expressions): классы, реализующие абстрактное выражение и определяющие конкретные правила интерпретации.
  4. Клиент (Client): класс, который создает и использует интерпретатор.

Пример на Java

Рассмотрим пример, в котором мы создаем простой интерпретатор для арифметических выражений, состоящих из чисел и операций сложения и вычитания.

import java.util.HashMap;
import java.util.Map;

// Интерфейс выражения
interface Expression {
    int interpret(Map<String, Integer> context);
}

// Конкретное выражение: Число
class NumberExpression implements Expression {
    private int number;

    public NumberExpression(int number) {
        this.number = number;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return number;
    }
}

// Конкретное выражение: Переменная
class VariableExpression implements Expression {
    private String variable;

    public VariableExpression(String variable) {
        this.variable = variable;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return context.get(variable);
    }
}

// Конкретное выражение: Сложение
class AddExpression implements Expression {
    private Expression left;
    private Expression right;

    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return left.interpret(context) + right.interpret(context);
    }
}

// Конкретное выражение: Вычитание
class SubtractExpression implements Expression {
    private Expression left;
    private Expression right;

    public SubtractExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return left.interpret(context) - right.interpret(context);
    }
}

// Пример использования
public class InterpreterPatternExample {
    public static void main(String[] args) {
        // Создаем контекст с переменными
        Map<String, Integer> context = new HashMap<>();
        context.put("x", 10);
        context.put("y", 5);

        // Создаем выражение: x + y - 2
        Expression expression = new SubtractExpression(
            new AddExpression(new VariableExpression("x"), new VariableExpression("y")),
            new NumberExpression(2)
        );

        // Интерпретируем выражение
        int result = expression.interpret(context);
        System.out.println("Результат: " + result); // Результат: 13
    }
}

Объяснение кода:

  1. Интерфейс Expression определяет метод interpret, который принимает контекст и возвращает результат интерпретации.
  2. Класс NumberExpression представляет числовое значение и возвращает его при интерпретации.
  3. Класс VariableExpression представляет переменную и возвращает ее значение из контекста.
  4. Классы AddExpression и SubtractExpression представляют операции сложения и вычитания соответственно. Они принимают два выражения и интерпретируют их, выполняя соответствующую операцию.
  5. В методе main мы создаем контекст с переменными и выражение x + y - 2, а затем интерпретируем его, получая результат.

Таким образом, паттерн "Интерпретатор" позволяет создавать интерпретаторы для языков или выражений, определяя грамматику и правила интерпретации с помощью классов. Это делает код более структурированным и легким для расширения, если необходимо добавить новые операции или правила.