O livro "JAVA and Patterns" do Dr. Yan Hong começa com uma descrição do padrão Interpreter:
O padrão de intérprete é um padrão comportamental para classes. Dada uma linguagem, o padrão intérprete define uma representação de sua gramática e fornece um intérprete. Os clientes podem usar este intérprete para interpretar frases neste idioma.
A estrutura do modo intérprete
Tomemos um sistema esquemático como exemplo para discutir a estrutura do modo intérprete. O diagrama da estrutura do sistema é o seguinte:
As funções envolvidas no padrão são as seguintes:
(1) Função de expressão abstrata (Expressão): Declare uma interface abstrata que todas as funções de expressão concreta precisam implementar. Esta interface é principalmente um método interpret(), chamado de operação de interpretação.
(2) Função de expressão terminal: implementa a interface exigida pela função de expressão abstrata, principalmente um método interpret(). Cada símbolo terminal na gramática possui uma expressão terminal específica correspondente; Por exemplo, existe uma fórmula simples R=R1+R2, na qual R1 e R2 são símbolos terminais, e o interpretador correspondente que analisa R1 e R2 é uma expressão terminal.
(3) Função de expressão não terminal: cada regra na gramática requer uma expressão não terminal específica. As expressões não terminais são geralmente operadores ou outras palavras-chave na gramática, como fórmulas. Em R = R1 + R2, "+" é um símbolo não terminal. , e o interpretador que analisa "+" é uma expressão de símbolo não terminal.
(4) Função de contexto: A tarefa desta função é geralmente armazenar os valores específicos correspondentes a cada símbolo terminal na gramática. Por exemplo, R=R1+R2, atribuímos um valor de 100 a R1 e um valor de. 200 a R2. Essas informações precisam ser armazenadas na função de ambiente. Em muitos casos, basta usarmos o Map para atuar como função de ambiente.
Para ilustrar a implementação do modo intérprete, aqui está a gramática mais simples e a implementação correspondente do modo intérprete, que simula a operação e avaliação de expressões booleanas na linguagem Java.
Os símbolos terminais nesta linguagem são variáveis booleanas, ou seja, as constantes verdadeiro e falso. Expressões não terminais incluem expressões booleanas, como operadores e, ou e não. Esta gramática simples é a seguinte:
Copie o código do código da seguinte forma:
Expressão ::= Constante |
E ::= Expressão 'AND' Expressão
Ou ::= Expressão 'OU' Expressão
Não ::= Expressão 'NÃO'
Variável ::= qualquer identificador
Constante ::= 'verdadeiro' |
O diagrama de estrutura do modo intérprete é o seguinte:
código fonte
papel de expressão abstrata
Copie o código do código da seguinte forma:
classe abstrata pública Expressão {
/**
* Sujeito ao ambiente, este método interpreta qualquer expressão
*/
interpretação booleana abstrata pública (contexto ctx);
/**
* Verifique se duas expressões são estruturalmente iguais
*/
público abstrato booleano igual a (Objeto obj);
/**
* Retorna o código hash da expressão
*/
público abstrato int hashCode();
/**
* Converta a expressão em uma string
*/
público abstrato String toString();
}
Um objeto Constant representa uma constante booleana
Copie o código do código da seguinte forma:
classe pública Constante estende Expressão{
valor booleano privado;
constante pública(valor booleano){
este.valor = valor;
}
@Substituir
público booleano igual a(Objeto obj) {
if(obj != null && obj instanceof Constant){
retornar este.valor == ((Constante)obj).valor;
}
retornar falso;
}
@Substituir
public int hashCode() {
retornar this.toString().hashCode();
}
@Substituir
interpretação booleana pública (contexto ctx) {
valor de retorno;
}
@Substituir
string pública paraString() {
retornar novo Boolean(valor).toString();
}
}
Um objeto Variable representa uma variável nomeada. O código é o seguinte:
variável de classe pública estende expressão {
nome da string privada;
Variável pública (nome da string){
este.nome = nome;
}
@Substituir
público booleano igual a(Objeto obj) {
if (obj! = null && obj instância da variável)
{
retorne este.nome.equals(
((Variável)obj).nome);
}
retornar falso;
}
@Substituir
public int hashCode() {
retornar this.toString().hashCode();
}
@Substituir
string pública paraString() {
nome de retorno;
}
@Substituir
interpretação booleana pública (contexto ctx) {
retornar ctx.lookup(este);
}
}
A classe And representa a operação lógica "AND", que representa a operação de fornecer uma nova expressão booleana a partir de duas expressões booleanas por meio da operação lógica "AND".
Copie o código do código da seguinte forma:
classe pública e estende a expressão {
expressão privada esquerda, direita;
public And(Expressão à esquerda, Expressão à direita){
isto.esquerda = esquerda;
isto.certo = certo;
}
@Substituir
público booleano igual a(Objeto obj) {
if (obj! = null && obj instância de And)
{
retornar esquerda.equals(((E)obj).esquerda) &&
certo.equals(((E)obj).direito);
}
retornar falso;
}
@Substituir
public int hashCode() {
retornar this.toString().hashCode();
}
@Substituir
interpretação booleana pública (contexto ctx) {
retornar esquerda.interpret(ctx) && direita.interpret(ctx);
}
@Substituir
string pública paraString() {
return "(" + left.toString() + " AND " + right.toString() + ")";
}
}
A classe Or representa a operação lógica "OR", que representa a operação de fornecer uma nova expressão booleana a partir de duas expressões booleanas por meio da operação lógica "OR".
Copie o código do código da seguinte forma:
classe pública ou estende a expressão {
expressão privada esquerda, direita;
public Or(Expressão à esquerda, Expressão à direita){
isto.esquerda = esquerda;
isto.certo = certo;
}
@Substituir
público booleano igual a(Objeto obj) {
if (obj! = null && obj instância de Ou)
{
retornar this.left.equals(((Or)obj).left) && this.right.equals(((Or)obj).right);
}
retornar falso;
}
@Substituir
public int hashCode() {
retornar this.toString().hashCode();
}
@Substituir
interpretação booleana pública (contexto ctx) {
retornar esquerda.interpretar(ctx) || direita.interpretar(ctx);
}
@Substituir
string pública paraString() {
return "(" + left.toString() + "OU" + right.toString() + ")";
}
}
A classe Not representa a operação lógica "not", que representa a operação de fornecer uma nova expressão booleana a partir de uma expressão booleana por meio da operação lógica "not".
classe pública Não estende Expressão {
Expressão privada exp;
public Not(Expressão exp){
isto.exp = exp;
}
@Substituir
público booleano igual a(Objeto obj) {
if (obj! = null && obj instância de Not)
{
retornar exp.equals(
((Não)obj).exp);
}
retornar falso;
}
@Substituir
public int hashCode() {
retornar this.toString().hashCode();
}
@Substituir
interpretação booleana pública (contexto ctx) {
return !exp.interpret(ctx);
}
@Substituir
string pública paraString() {
return "(Não " + exp.toString() + ")";
}
}
A classe Context define um mapeamento de variáveis para valores booleanos
Copie o código do código da seguinte forma:
classe pública Contexto {
private Map<Variável,Boolean> map = new HashMap<Variável,Boolean>();
public void atribuir(Variável var, valor booleano){
map.put(var, new Boolean(valor));
}
pesquisa booleana pública (variável var) lança IllegalArgumentException{
Valor booleano = map.get(var);
if(valor == nulo){
lançar new IllegalArgumentException();
}
return valor.booleanValue();
}
}
Classe de cliente
Copie o código do código da seguinte forma:
classe pública Cliente {
public static void main(String[] args) {
Contexto ctx = new Contexto();
Variável x = nova Variável("x");
Variável y = nova Variável("y");
Constante c = nova Constante(verdadeiro);
ctx.assign(x, falso);
ctx.assign(y, verdadeiro);
Expressão exp = new Or(new And(c,x) , new And(y,new Not(x)));
System.out.println("x=" + x.interpret(ctx));
System.out.println("y=" + y.interpret(ctx));
System.out.println(exp.toString() + "=" + exp.interpret(ctx));
}
}
Os resultados da execução são os seguintes: