The Interpreter Pattern of Java Design Patterns

Reprinted: https://blog.csdn.net/zhengzhb/article/details/7666020

Definition: Given a language, define a representation of its grammar and define an interpreter that uses that representation to interpret sentences in the language.

Type: Behavioral Pattern

Class Diagram:

        The interpreter mode is a relatively rarely used mode, and I have never used this mode before. Let's take a look at the interpreter mode.

 

Structure of Interpreter Mode

  • Abstract interpreter: declares an abstract interface (or abstract class) that all concrete expressions must implement. The interface is mainly an interpret() method, which is called an interpretation operation. The specific interpretation task is completed by its various implementation classes, and the specific interpreter is completed by the terminal interpreter TerminalExpression and the non-terminal interpreter NonterminalExpression respectively.
  • Terminal expression: Implements interpretation operations associated with elements in the grammar. Usually, there is only one terminal expression in an interpreter mode, but there are multiple instances, corresponding to different terminals. Half of the terminal symbols are the operation units in the grammar. For example, there is a simple formula R=R1+R2, in which R1 and R2 are the terminal symbols, and the corresponding interpreter that parses R1 and R2 is the terminal symbol expression.                                
  • Non-terminal expression: each rule in the grammar corresponds to a non-terminal expression. Non-terminal expressions are generally operators or other keywords in the grammar. For example, in the formula R=R1+R2, + is non-terminal. Terminal, the interpreter that parses + is a non-terminal expression. Nonterminal expressions increase according to the complexity of the logic, and in principle each grammar rule corresponds to a nonterminal expression.
  • Environment role: The task of this role is generally used to store the specific values ​​corresponding to each terminal symbol in the grammar, such as R=R1+R2, we assign 100 to R1 and 200 to R2. This information needs to be stored in the environment role. In many cases, it is enough for us to use Map to act as the environment role.

Code

[java]  view plain copy  
  1. class Context {}  
  2. abstractclass Expression {   
  3.     publicabstract Object interpreter(Context ctx);   
  4. }  
  5. class TerminalExpression extends Expression {  
  6.     public Object interpreter(Context ctx){  
  7.         returnnull;   
  8.     }  
  9. }  
  10. class NonterminalExpression extends Expression {  
  11.     public NonterminalExpression(Expression...expressions){  
  12.           
  13.     }  
  14.     public Object interpreter(Context ctx){  
  15.         returnnull;   
  16.     }  
  17. }  
  18. public class  Customer {   
  19.     publicstaticvoid main(String[] args){    
  20.         String expression = "";  
  21.         char[] charArray = expression.toCharArray();  
  22.         Context ctx = new Context();  
  23.         Stack<Expression> stack = new Stack<Expression>();  
  24.         for(int i=0;i<charArray.length;i++){  
  25.             / / Make syntax judgment, recursive call  
  26.         }  
  27.         Expression exp = stack.pop();  
  28.         exp.interpreter(ctx);  
  29.     }  
  30. }  

        The code part of grammar recursion needs to be implemented according to the specific situation, so it is not reflected in the code. Abstract expressions are the key to generating grammar sets. Each non-terminal expression interprets a minimum grammar unit, and then recursively combines these grammar units into a complete grammar. This is the interpreter pattern.

 

Pros and Cons of Interpreter Mode

        The interpreter is a simple syntax analysis tool. Its most significant advantage is its extensibility. To modify the grammar rules, you only need to modify the corresponding non-terminal symbols. If you expand the grammar, you only need to add non-terminal symbol classes.

        However, the interpreter mode will cause class expansion, and each grammar needs to generate a non-terminal expression. When the grammar rules are complex, a large number of class files may be generated, which brings a lot of trouble to maintenance. At the same time, due to the recursive calling method, each non-terminal expression only cares about the expression related to itself, and each expression needs to know the final result, which must be recursive, whether it is an object-oriented language or a procedure-oriented language. , recursion is a deprecated way. Efficiency is a non-negligible issue due to the use of lots of loops and recursion. Especially when interpreting a parsing complex, verbose grammar, the efficiency is unbearable.

 

Applicable Scenarios for Interpreter Mode

        Interpreter mode can be used in the following situations:

  • There is a simple grammar rule, such as a sql statement, if we need to perform rm conversion according to the sql statement, we can use the interpreter mode to interpret the statement.
  • Some recurring problems, such as the four operations of addition, subtraction, multiplication and division, but the formula is different each time, sometimes a+bc*d, sometimes a*b+cd, etc., etc. The formulas are ever-changing, but they are all determined by adding Subtraction, multiplication and division of four non-terminal symbols are connected, then we can use the interpreter mode.

Precautions

       The interpreter mode is really a relatively rarely used mode, because it is too troublesome to maintain. Imagine a bunch of non-terminal interpreters, if you don't know the rules of the grammar well in advance, or the grammar Especially simple, it is difficult to read its logic. The interpreter mode is rarely used in actual system development, because it will cause efficiency, performance and maintenance problems.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325810414&siteId=291194637