Java description design pattern (14): Interpreter pattern

Source code: GitHub point here || GitEE point here

I. interpreter mode

1. Basic concept

Interpreter mode is the behavior mode of an object. Given a language, the Interpreter pattern can define a representation of its grammar and provide an interpreter at the same time. The client can use this interpreter to interpret expressions in this language.

2. Mode diagram

3. Core role

(1) abstract expression

Express: declare the abstract interface that the concrete expression role needs to implement. This interface mainly provides an interpret() method, which is called interpretation operation.

(2) terminator expression

TerminalExpress: implements the abstract expression role interface, mainly an interpret() method; each terminator has a specific end expression corresponding to it. For example, the interpreter that resolves c=a+b, a and b are terminators, and the interpreter that resolves a and b is terminator expressions.

(3) non terminal expression

NotTerminalExpress: each rule needs a specific non terminal expression to join, which generally refers to operator or logical judgment, such as c=a+b, "+" is non terminal, and the interpreter resolving "+" is a non terminal expression.

(4) environmental container

DataMap: it is generally used to store the specific values corresponding to each terminator. For example, c=a+b is converted to c=1+2. This information requires a storage environment.

4. Source code implementation

  • Class diagram structure

  • Source code implementation
public class C01_InScene {
    public static void main(String[] args) {
        DataMap dataMap = new DataMap();
        TerminalExpress terminalExpress1 = new TerminalExpress("num1");
        TerminalExpress terminalExpress2 = new TerminalExpress("num2");
        TerminalExpress terminalExpress3 = new TerminalExpress("num3");
        dataMap.putData(terminalExpress1, 1);
        dataMap.putData(terminalExpress2, 2);
        dataMap.putData(terminalExpress3, 3);
        // 1+2-3 = 0
        System.out.println(new Minus(
                           new Add(terminalExpress1,terminalExpress2), terminalExpress3)
                           .interpret(dataMap));
    }
}
// Interpreter interface
interface Express {
    Integer interpret(DataMap dataMap) ;
}
// Nonterminal expression
abstract class NotTerminalExpress implements Express {
    Express express1,express2;
    public NotTerminalExpress(Express express1, Express express2){
        this.express1 = express1;
        this.express2 = express2;
    }
}
// Terminator expression: 1 + 2 terminators: 1 and 2
class TerminalExpress implements Express {
    public String field ;
    public TerminalExpress (String field){
        this.field = field ;
    }
    @Override
    public Integer interpret(DataMap dataMap) {
        return dataMap.getData(this);
    }
}
// additive expression 
class Add extends NotTerminalExpress {
    public Add (Express e1, Express e2) {
        super(e1, e2);
    }
    // Subtract two expressions
    @Override
    public Integer interpret(DataMap context) {
        return this.express1.interpret(context) + this.express2.interpret(context);
    }
}
// Subtraction expression
class Minus extends NotTerminalExpress {
    public Minus (Express e1, Express e2) {
        super(e1, e2);
    }
    // Subtract two expressions
    @Override
    public Integer interpret(DataMap context) {
        return this.express1.interpret(context) - this.express2.interpret(context);
    }
}
// Data container
class DataMap {
    private Map<Express,Integer> dataMap = new HashMap<>() ;
    public void putData (Express key,Integer value){
        dataMap.put(key,value) ;
    }
    public Integer getData (Express key){
        return dataMap.get(key) ;
    }
}

II. Spring framework application

1. Source code case

import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class SpringTest {
    public static void main(String[] args) {
        SpelExpressionParser parser = new SpelExpressionParser () ;
        Expression expression = parser.parseExpression("(1+3-2)*3") ;
        Integer result = (Integer)expression.getValue() ;
        System.out.println("result="+result);
    }
}

2. Code analysis

(1)Expression structure

Expression interface: has different implementation classes.

interface Expression
class CompositeStringExpression implements Expression
class LiteralExpression implements Expression
class SpelExpression implements Expression

Core approach:

Object getValue() throws EvaluationException;

(2)SpelExpressionParser structure

SpelExpressionParser extends TemplateAwareExpressionParser
TemplateAwareExpressionParser implements ExpressionParser
interface ExpressionParser

(3)ExpressionParser interface

public interface ExpressionParser {
    Expression parseExpression(String var1) ;
    Expression parseExpression(String var1, ParserContext var2) ;
}

(4) get expression

Get different Expression objects according to different conditions. The class dependency is generated here.

Source location: TemplateAwareExpressionParser

public Expression parseExpression(String expressionString, 
                                  ParserContext context) 
                                  throws ParseException {
        if (context == null) {
            context = NON_TEMPLATE_PARSER_CONTEXT;
        }
        return context.isTemplate() ? 
        this.parseTemplate(expressionString, context) : 
        this.doParseExpression(expressionString, context);
    }

III. model summary

  • scene

Compiler, operator expression, regular expression, robot, etc.

  • Advantage

When an expression or language needs to be interpreted and executed, the content in this scenario can consider using interpreter mode, so that the program has good scalability.

  • shortcoming

The interpreter mode will cause class expansion, which will make the program execution and debugging very complex and not easy to understand.

IV. source code address

GitHub·address
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·address
https://gitee.com/cicadasmile/model-arithmetic-parent

Keywords: Programming github Spring

Added by xardas on Thu, 17 Oct 2019 16:50:00 +0300