Re-aprendizaje de patrones de diseño (3. Patrones de diseño-patrones de intérprete)

1. Modo intérprete

    El modo intérprete es en realidad algunos esquemas para analizar de acuerdo con cierta gramática. Puede ser relativamente raro que nosotros mismos escribamos tales reglas de análisis, pero aún podemos usar muchas de ellas en momentos normales. Por ejemplo, las expresiones regulares, expresiones EL, expresiones matemáticas, etc. que usamos son todas aplicaciones de intérpretes.

1.1, qué es el modo intérprete

  • definición

    El patrón de intérprete es un patrón de diseño de comportamiento que, dado un idioma, define una representación de su gramática y usa esa representación para interpretar oraciones en el idioma.

    La estructura del modo intérprete:

    1) Función de expresión abstracta (Expresión abstracta): define la interfaz del intérprete, acuerda la operación de interpretación del intérprete, incluyendo principalmente el método de interpretación interpret();

    2) El papel de la expresión terminal: implementar el método de interpretación relacionado con el símbolo terminal en la gramática, y cada terminal en la gramática tiene una expresión terminal específica que le corresponde;

    3) Rol de expresión no terminal (Expresión no terminal): también es una subclase de expresión abstracta, utilizada para implementar operaciones relacionadas con símbolos no terminales en la gramática, y cada regla en la gramática corresponde a una expresión no terminal;

    4) Función de entorno (contexto): se utiliza para almacenar información global fuera del intérprete, por lo general almacena temporalmente declaraciones que deben interpretarse.

   La intención del modo intérprete es permitirle componer y ejecutar objetos de acuerdo con algunas reglas gramaticales definidas por la implementación.

1.2 Ventajas y desventajas del modo intérprete

  • ventaja

    Buena escalabilidad, utilizando clases en modo intérprete para representar las reglas gramaticales del lenguaje, de modo que la gramática pueda ser cambiada o ampliada a través de mecanismos como la herencia;

  • defecto

    1) Provocará la expansión de clases. Cada regla debe definir al menos una clase. Cuando se incluyen muchas reglas gramaticales, el número de clases también será grande, lo que dificulta la administración y el mantenimiento del sistema;

    2) El problema de la eficiencia de ejecución es bajo. Se puede usar una gran cantidad de bucles y recursiones cuando se analizan las reglas. La eficiencia es un problema que no se puede ignorar.

1.3 Método de creación

    Tome la suma, resta, multiplicación y división de las matemáticas chinas a la suma, resta, multiplicación y división de números arábigos como ejemplo.

1) Rol de contexto

//环境类
public class Context {

    Map<String,Integer> dict = new HashMap<String,Integer>();
	
    private String exp;
    
	public Context(String exp){
		this.exp = exp;
		dict.put("一", 1);
		dict.put("二", 2);
		dict.put("三", 3);
		dict.put("四", 4);
		dict.put("五", 5);
		dict.put("六", 6);
		dict.put("七", 7);
		dict.put("八", 8);
		dict.put("九", 9);
	}

	public Map<String, Integer> getDict() {
		return dict;
	}

	public String getExp() {
		return exp;
	}

	public void setExp(String exp) {
		this.exp = exp;
	}

}

2) Función de expresión abstracta

//抽象表达式类
public abstract class AbstractExpression {
	
	public abstract void interpret(Context context);
	
}

3) El papel de la Expresión Terminal

public class TerminalExpression extends AbstractExpression{

	@Override
	public void interpret(Context context) {
		if(context!=null && !"".equals(context.getExp())){
			String exp = context.getExp();
			for (String str : context.getDict().keySet()) {
				if(exp.contains(str)){
					Integer s = context.getDict().get(str);
					exp = exp.replace(str, s+"");
				}
			}
			context.setExp(exp);
		}
	}

}

4) Función de expresión no terminal (expresión no terminal)

public class NonterminalExpression extends AbstractExpression{

	@Override
	public void interpret(Context context) {
		String exp = context.getExp();
		if (exp.contains("加"))
        {
            exp= exp.replace("加","+");
        }
        if (exp.contains("减"))
        {
            exp= exp.replace("减", "-");
        }
        if (exp.contains("乘"))
        {
            exp= exp.replace("乘", "*");
        }
        if (exp.contains("除"))
        {
            exp= exp.replace("除", "/");
        }
        context.setExp(exp);
	}

}

5) cliente

public class Client {

	public static void main(String[] args) {
		Context context = new Context("一加二加三减二乘三除三");
		AbstractExpression abstractExpression = new TerminalExpression();
		abstractExpression.interpret(context);
		AbstractExpression noabstractExpression = new NonterminalExpression();
        noabstractExpression.interpret(context);
        System.out.println(context.getExp());
	}
}
//输出结果:1+2+3-2*3/3

1.4 Resumen y sugerencias

    En el proceso de construcción de software, si los problemas en un campo específico son más complicados y situaciones similares aparecen repetidamente, pero el uso de métodos de programación ordinarios puede resultar muy engorroso y poco flexible, y enfrentar modificaciones muy frecuentes, en este caso, usar el modo intérprete puede ser una mejor opción.

    De hecho, este modo también se ha utilizado para procesar datos de impresión en desarrollo antes. Algunas conversiones de datos de impresión, interceptación y nueva línea se escriben en el archivo de configuración, y una serie de reglas se escriben en el archivo de configuración como un procesamiento general (pero no tan estandarizadas como se escriben en el modo de intérprete).

Escenario de aplicación:

    Cuando un idioma necesita ser interpretado y puede expresar las oraciones en el idioma como un árbol de sintaxis abstracta, puede usar el modo de intérprete.

Aplicación del modo intérprete en JDK:

    java.util.regex.Patrón

Supongo que te gusta

Origin blog.csdn.net/xiaoxianer321/article/details/125476669
Recomendado
Clasificación