El libro del Dr. Yan Hong "JAVA and Patterns" comienza con una descripción del patrón Interpreter:
El patrón de intérprete es un patrón de comportamiento para las clases. Dado un idioma, el patrón de intérprete define una representación de su gramática y proporciona un intérprete. Los clientes pueden utilizar este intérprete para interpretar oraciones en este idioma.
La estructura del modo intérprete.
Tomemos un sistema esquemático como ejemplo para discutir la estructura del modo intérprete. El diagrama de estructura del sistema es el siguiente:
Los roles involucrados en el patrón son los siguientes:
(1) Rol de expresión abstracta (Expresión): declara una interfaz abstracta que todos los roles de expresión concreta deben implementar. Esta interfaz es principalmente un método interpreta(), llamado operación de interpretación.
(2) Función de expresión terminal: implementa la interfaz requerida por la función de expresión abstracta, principalmente un método interpreta () a cada símbolo terminal en la gramática le corresponde una expresión terminal específica; Por ejemplo, existe una fórmula simple R = R1 + R2, en la que R1 y R2 son símbolos terminales, y el intérprete correspondiente que analiza R1 y R2 es una expresión terminal.
(3) Función de expresión no terminal: cada regla de la gramática requiere una expresión no terminal específica. Las expresiones no terminales generalmente son operadores u otras palabras clave en la gramática, como fórmulas. En R = R1 + R2, "+" es un símbolo no terminal. , y el intérprete que analiza "+" es una expresión de símbolo no terminal.
(4) Rol de contexto: la tarea de este rol generalmente es almacenar los valores específicos correspondientes a cada símbolo terminal en la gramática. Por ejemplo, R = R1 + R2, asignamos un valor de 100 a R1 y un valor de. 200 a R2. Esta información debe almacenarse en la función del entorno. En muchos casos, es suficiente que utilicemos Map para que actúe como la función del entorno.
Para ilustrar la implementación del modo de intérprete, aquí se presenta la gramática más simple y la implementación correspondiente del modo de intérprete, que consiste en simular la operación y evaluación de expresiones booleanas en el lenguaje Java.
Los símbolos terminales en este lenguaje son variables booleanas, es decir, las constantes verdadero y falso. Las expresiones no terminales incluyen expresiones booleanas como operadores y, o y no. Esta gramática simple es la siguiente:
Copie el código de código de la siguiente manera:
Expresión ::= Constante | Variable | O | No |
Y ::= Expresión 'Y' Expresión
O ::= Expresión 'O' Expresión
No ::= Expresión 'NO'
Variable ::= cualquier identificador
Constante ::= 'verdadero' | 'falso'
El diagrama de estructura del modo intérprete es el siguiente:
código fuente
papel de expresión abstracta
Copie el código de código de la siguiente manera:
Expresión de clase abstracta pública {
/**
* Sujeto al entorno, este método interpreta cualquier expresión dada.
*/
interpretación booleana abstracta pública (Contexto ctx);
/**
* Comprobar si dos expresiones son estructuralmente iguales
*/
booleano abstracto público es igual (Objeto obj);
/**
* Devuelve el código hash de la expresión.
*/
resumen público int hashCode();
/**
* Convertir la expresión en una cadena.
*/
Cadena abstracta pública toString();
}
Un objeto constante representa una constante booleana
Copie el código de código de la siguiente manera:
clase pública Constante extiende Expresión {
valor booleano privado;
Constante pública (valor booleano) {
this.value = valor;
}
@Anular
público booleano es igual (Objeto obj) {
if(obj!= null && obj instancia de constante){
devuelve this.value == ((Constant)obj).value;
}
devolver falso;
}
@Anular
público int código hash() {
devolver this.toString().hashCode();
}
@Anular
interpretación booleana pública (Contexto ctx) {
valor de retorno;
}
@Anular
Cadena pública toString() {
devolver nuevo booleano(valor).toString();
}
}
Un objeto Variable representa una variable con nombre. El código es el siguiente:
La variable de clase pública extiende la expresión {
nombre de cadena privada;
Variable pública (nombre de cadena) {
this.nombre = nombre;
}
@Anular
público booleano es igual (Objeto obj) {
si (obj! = nulo && obj instancia de variable)
{
devolver este.nombre.es igual a (
((Variable)obj).nombre);
}
devolver falso;
}
@Anular
público int código hash() {
devolver this.toString().hashCode();
}
@Anular
Cadena pública toString() {
nombre de retorno;
}
@Anular
interpretación booleana pública (Contexto ctx) {
devolver ctx.lookup(esto);
}
}
La clase Y representa la operación lógica "Y", que representa la operación de dar una nueva expresión booleana a partir de dos expresiones booleanas mediante la operación lógica "Y".
Copie el código de código de la siguiente manera:
clase pública y extiende la expresión {
expresión privada izquierda, derecha;
public And(Expresión izquierda, Expresión derecha){
this.left = izquierda;
this.right = correcto;
}
@Anular
público booleano es igual (Objeto obj) {
si (obj! = nulo && obj instancia de Y)
{
devolver izquierda.equals(((Y)obj).izquierda) &&
right.equals(((Y)obj).right);
}
devolver falso;
}
@Anular
público int código hash() {
devolver this.toString().hashCode();
}
@Anular
interpretación booleana pública (Contexto ctx) {
return izquierda.interpretar(ctx) && derecha.interpretar(ctx);
}
@Anular
Cadena pública toString() {
return "(" + left.toString() + " AND " + right.toString() + ")";
}
}
La clase Or representa la operación lógica "O", que representa la operación de dar una nueva expresión booleana a partir de dos expresiones booleanas mediante la operación lógica "O".
Copie el código de código de la siguiente manera:
clase pública O extiende la expresión {
expresión privada izquierda, derecha;
público O (Expresión izquierda, Expresión derecha){
this.left = izquierda;
this.right = correcto;
}
@Anular
público booleano es igual (Objeto obj) {
si (obj! = nulo && obj instancia de O)
{
return this.left.equals(((O)obj).left) && this.right.equals(((O)obj).right);
}
devolver falso;
}
@Anular
público int código hash() {
devolver this.toString().hashCode();
}
@Anular
interpretación booleana pública (Contexto ctx) {
devolver izquierda.interpretar(ctx) || derecha.interpretar(ctx);
}
@Anular
cadena pública toString() {
return "(" + left.toString() + "O" + right.toString() + ")";
}
}
La clase Not representa la operación lógica "no", que representa la operación de dar una nueva expresión booleana a partir de una expresión booleana mediante la operación lógica "no". Copie el código de la siguiente manera:
clase pública No extiende la expresión {
expresión privada exp;
público No(Expresión exp){
esto.exp = exp;
}
@Anular
público booleano es igual (Objeto obj) {
si (obj! = nulo && obj instancia de no)
{
devolver exp.igual(
((No)obj).exp);
}
devolver falso;
}
@Anular
público int código hash() {
devolver this.toString().hashCode();
}
@Anular
interpretación booleana pública (Contexto ctx) {
retorno !exp.interpret(ctx);
}
@Anular
Cadena pública toString() {
return "(No " + exp.toString() + ")";
}
}
La clase Contexto define un mapeo de variables a valores booleanos.
Copie el código de código de la siguiente manera:
Contexto de clase pública {
mapa privado<Variable,Booleano> mapa = nuevo HashMap<Variable,Booleano>();
asignación de vacío público (var variable, valor booleano) {
map.put(var, nuevo booleano(valor));
}
la búsqueda booleana pública (var variable) arroja IllegalArgumentException {
Valor booleano = map.get(var);
si(valor == nulo){
lanzar nueva IllegalArgumentException();
}
valor de retorno.booleanValue();
}
}
clase de cliente
Copie el código de código de la siguiente manera:
Cliente de clase pública {
público estático vacío principal (String [] argumentos) {
Contexto ctx = nuevo contexto();
Variable x = nueva Variable ("x");
Variable y = nueva Variable("y");
Constante c = nueva Constante (verdadera);
ctx.assign(x,falso);
ctx.assign(y, verdadero);
Expresión 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));
}
}
Los resultados de ejecución son los siguientes: