Notas de patrones de intérprete de patrones de diseño

ilustrar

Registre el método de escritura para aprender el patrón de diseño-intérprete. La versión de JDK utilizada es la versión 1.8.

Intérprete(intérprete)

Intención : definir un idioma, definir una representación de su gramática y definir un intérprete que use esa representación para interpretar oraciones en el idioma.
Estructura :
Insertar descripción de la imagen aquí

en:

  • AbstractExpression declara la operación de interpretación de un programa. Esta interfaz es compartida por todos los nodos en el árbol de sintaxis abstracta.
  • TerminalExpression implementa las operaciones de interpretación asociadas con los símbolos terminales en una gramática; cada símbolo terminal en una oración requiere una instancia de esta clase.
  • NonterminalExpression requiere una clase NonterminalExpression para cada regla en la gramática; mantiene una variable de instancia del tipo AbstractExpression para cada símbolo; e implementa la operación de interpretación (Interpret) para los símbolos no terminales en la gramática.
  • El contexto contiene información global fuera del intérprete.
  • El Cliente construye (o recibe) un árbol de sintaxis abstracta que representa una oración específica en el lenguaje definido por esta gramática. El árbol de sintaxis abstracta se ensambla a partir de instancias de NonterminaExpression y TerminalExpression; llama a la operación de interpretación.

aplicabilidad:

  • Cuando la gramática del lenguaje es simple y la eficiencia de la ejecución no es un tema crítico.
  • Cuando un problema vuelve a ocurrir y se puede expresar en un lenguaje sencillo.
  • Cuando un idioma necesita ser interpretado y ejecutado, las oraciones en el idioma se pueden representar como un árbol de sintaxis abstracta.

Tabla de contenido

Insertar descripción de la imagen aquí

Diagrama de clases de ejemplo de patrón de intérprete

Insertar descripción de la imagen aquí
Implemente el ejemplo del patrón Interpreter con este diagrama de clases UML.

clase de expresión abstracta

package com.example.deesign_patterns.interpreter;

//抽象表达式类
public abstract class AbstractExpression {
    
    

    public abstract int interpret(Context context);
}

Clase de rol ambiental

package com.example.deesign_patterns.interpreter;

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

//环境角色类
public class Context {
    
    

    //定义一个map集合,用来存储变量及对应的值
    private Map<Variable,Integer> map=new HashMap<Variable,Integer>();

    //添加变量的功能
    public void assign(Variable var,Integer value){
    
    
        map.put(var,value);
    }

    //根据变量获取对应的值
    public int getValue(Variable var){
    
    
        return map.get(var);
    }
}

clase que encapsula variables

package com.example.deesign_patterns.interpreter;

//封装变量的类
public class Variable extends AbstractExpression{
    
    

    //声明存储变量名的成员变量
    private String name;

    public Variable(String name) {
    
    
        this.name = name;
    }

    @Override
    public int interpret(Context context) {
    
    
        //直接返回变量的值
        return context.getValue(this);
    }

    @Override
    public String toString() {
    
    
        return name;
    }
}

Clase de expresión de suma

package com.example.deesign_patterns.interpreter;

//加法表达式类
public class Plus extends AbstractExpression{
    
    

    //加号左边的表达式
    private AbstractExpression left;
    //加号右边的表达式
    private AbstractExpression right;

    public Plus(AbstractExpression left, AbstractExpression right) {
    
    
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
    
    
        //将左边表达式的结果和右边表达式的结果进行相加
        return left.interpret(context)+right.interpret(context);
    }

    @Override
    public String toString() {
    
    
        return "("+left.toString()+"+"+right.toString()+")";
    }
}

Clase de expresión de resta

package com.example.deesign_patterns.interpreter;

//减法表达式类
public class Minus extends AbstractExpression{
    
    

    //减法左边的表达式
    private AbstractExpression left;
    //减法右边的表达式
    private AbstractExpression right;

    public Minus(AbstractExpression left, AbstractExpression right) {
    
    
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
    
    
        //将左边表达式的结果和右边表达式的结果进行相减
        return left.interpret(context)-right.interpret(context);
    }

    @Override
    public String toString() {
    
    
        return "("+left.toString()+"-"+right.toString()+")";
    }
}

clase de prueba

package com.example.deesign_patterns.interpreter;

//测试类
public class Client {
    
    

    public static void main(String[] args) {
    
    
        //创建环境对象
        Context context=new Context();
        //创建多个变量对象
        Variable a=new Variable("a");
        Variable b=new Variable("b");
        Variable c=new Variable("c");
        Variable d=new Variable("d");
        //将变量存储到环境对象中
        context.assign(a,1);
        context.assign(b,2);
        context.assign(c,3);
        context.assign(d,4);
        //获取抽象语法树,如:(a-((b-c)+d))
        AbstractExpression expression=new Minus(a,new Plus(new Minus(b,c),d));
        //解释(计算)
        int result=expression.interpret(context);
        System.out.println(expression+"="+result);
    }
}

Insertar descripción de la imagen aquí

beneficio:

  • Fácil de cambiar y ampliar la gramática. Dado que las clases se utilizan en el patrón de resolución para representar las reglas gramaticales del idioma, la gramática se puede cambiar o ampliar mediante mecanismos como la herencia. Cada regla gramatical se puede representar como una clase, por lo que se puede implementar fácilmente un lenguaje simple.
  • Implementar gramáticas es más fácil. La implementación de cada clase de nodo de expresión en el árbol de sintaxis abstracta es similar y la escritura de código de estas clases no es particularmente complicada.
  • Es más conveniente agregar nuevas expresiones de interpretación. Si el usuario necesita agregar una nueva expresión de interpretación, solo necesita agregar una nueva expresión terminal o una clase de expresión no terminal. No es necesario modificar el código de la clase de expresión original y cumple con el "principio de apertura y cierre". .

defecto:

  • Es difícil mantener gramáticas complejas. En el modo intérprete, cada regla necesita definir al menos una clase, por lo que si un idioma contiene demasiadas reglas gramaticales, el número de clases aumentará dramáticamente, lo que hará que el sistema sea difícil de administrar y mantener.
  • La eficiencia de ejecución es baja. Debido a que se utiliza una gran cantidad de bucles y llamadas recursivas en el modo de intérprete, la interpretación de oraciones más complejas es muy lenta y el proceso de depuración del código también es más problemático.

Supongo que te gusta

Origin blog.csdn.net/weixin_48040732/article/details/131373953
Recomendado
Clasificación