O padrão Interpreter é um padrão de design comportamental que tem como objetivo principal definir uma representação gramatical para uma linguagem e um interpretador que usa essa representação para interpretar sentenças na linguagem. O problema que o padrão Interpreter tenta resolver inclui:
-
Interpretação de Linguagens e Gramáticas: Em muitos sistemas, pode ser necessário interpretar ou processar linguagens específicas (como linguagens de consulta, linguagens de programação ou linguagens de marcação). O padrão Interpreter fornece uma maneira de modelar e interpretar essas linguagens.
-
Extensibilidade da Interpretação: Para linguagens cujas gramáticas são relativamente fixas e não muito complexas, o Interpreter permite extender a interpretação adicionando novas maneiras de avaliar expressões ou novos tipos de expressões.
-
Separar a Interpretação da Implementação: Ao abstrair o processo de interpretação em classes e objetos distintos, o padrão separa a lógica de interpretação da lógica de negócios principal do sistema, facilitando a manutenção e a extensão.
Como Funciona
O padrão Interpreter geralmente envolve os seguintes componentes:
- Contexto: Contém informações globais que podem ser necessárias durante a interpretação.
- Expressão Abstrata: Define uma interface para interpretar um contexto particular.
- Expressão Terminal (TerminalExpression): Implementa a interface de Expressão Abstrata e interpreta símbolos terminais da gramática.
- Expressão Não Terminal (NonTerminalExpression): Também implementa a interface de Expressão Abstrata, mas é usada para interpretar regras gramaticais que requerem mais de um símbolo.
Exemplo
Um exemplo comum do uso do padrão Interpreter é em interpretadores de linguagens de programação ou linguagens de consulta, onde uma entrada do usuário (como uma expressão matemática ou uma consulta SQL) precisa ser interpretada e executada.
Vale ressaltar que para linguagens complexas ou em constante evolução, o uso do padrão Interpreter pode se tornar menos prático devido à complexidade da implementação da gramática e da manutenção. Em tais casos, outras abordagens, como o uso de compiladores ou interpretadores externos, podem ser mais adequadas.
Exemplo de Implementação
Vamos criar um exemplo simples do padrão Interpreter em Java. Vamos desenvolver um interpretador básico para expressões matemáticas que lidam apenas com adições e subtrações. Para manter a simplicidade, vamos considerar apenas números inteiros e operações binárias (ou seja, sempre dois operandos).
Interface da Expressão
Primeiro, definimos uma interface para todas as expressões:
public interface Expressao {
int interpretar();
}Expressões Terminais (Números)
Implementamos uma expressão terminal para números:
public class Numero implements Expressao {
private int numero;
public Numero(int numero) {
this.numero = numero;
}
@Override
public int interpretar() {
return numero;
}
}Expressões Não Terminais (Operações)
Implementamos expressões para adição e subtração:
public class Soma implements Expressao {
private Expressao esquerda;
private Expressao direita;
public Soma(Expressao esquerda, Expressao direita) {
this.esquerda = esquerda;
this.direita = direita;
}
@Override
public int interpretar() {
return esquerda.interpretar() + direita.interpretar();
}
}
public class Subtracao implements Expressao {
private Expressao esquerda;
private Expressao direita;
public Subtracao(Expressao esquerda, Expressao direita) {
this.esquerda = esquerda;
this.direita = direita;
}
@Override
public int interpretar() {
return esquerda.interpretar() - direita.interpretar();
}
}Utilizando o Interpretador
Finalmente, usamos o interpretador para avaliar uma expressão:
public class Main {
public static void main(String[] args) {
// Representa a expressão "1 + 2 - 3"
Expressao expressao = new Subtracao(
new Soma(new Numero(1), new Numero(2)),
new Numero(3)
);
int resultado = expressao.interpretar();
System.out.println("O resultado da expressão é: " + resultado);
}
}Neste exemplo, construímos uma expressão composta usando as classes Soma e Subtracao, que são interpretadas para calcular o resultado. O padrão Interpreter nos permite avaliar expressões compostas de maneira estruturada e extensível, facilitando a adição de novos tipos de operações ou expressões no futuro.