A brief introduction to Java design patterns: interpreter mode

definition

The interpreter model is a behavioral model of a class. Given a language, the interpreter model can define a representation of its grammar and provide an interpreter at the same time. The client can use this interpreter to interpret sentences in the language.

intention

Given a language, define its grammatical representation, and define an interpreter, this interpreter uses the identifier to interpret sentences in the language

Mainly solve the problem

Construct an interpreter to explain sentences for some fixed grammar

Pros and cons

advantage:

  • Good scalability and flexibility
  • Added a new way of interpreting expressions
  • Easy to implement simple grammar

Disadvantages:

  • Less usage scenarios
  • More difficult to maintain for complex grammar
  • Will cause class bloat
  • Using recursive calling method, low efficiency

structure

Insert picture description here
Roles involved:

  • Abstract expression (Expression) role: Declare an abstract interface that all concrete expression roles need to implement. This interface is mainly an interpret method called an interpretive operation
  • TerminalExpression (TerminalExpression) role: this is a specific role
    • Implemented the interface required by the role of abstract expression, mainly an interpret method
    • Each terminal symbol in the grammar has a specific terminal expression corresponding to it
  • Nonterminal Expression (NonterminalExpression) role: This is a specific role
    • Each rule in the grammar R=R1R2...Rn requires a specific non-terminal expression class
    • Each symbol in R=R1R2...Rn holds an instance variable of static type Expression
    • Implement the interpret method of the interpretation operation, and the interpretation operation recursively calls the above-mentioned instance variables representing the symbols in R1R2...Rn
  • Client role: build an abstract syntax tree, call interpretation operations
  • Context role: Provide some global information outside the interpreter, such as the true value of variables, etc.

Example

Abstract expression role:

/**
 * 这个抽象类代表终结类和非终结类的抽象化
 */
public abstract class Expression {
    
    

    /** 以环境类为准,本方法解释给定的任何一个表达式 */
    public abstract boolean interpret(Context ctx);

    /** 检验两个表达式在结构上是否相同 */
    public abstract boolean equals(Object o);

    /** 返回表达式的hashCode */
    public abstract int hashCode();

    /** 将表达式转换为字符串 */
    public abstract String toString();
}

End expression role:
Insert picture description here
a Constant object represents a Boolean constant

public class Constant extends Expression {
    
    
    private boolean value;

    public Constant(boolean value) {
    
    
        this.value = value;
    }

    /** 解释操作 */
    @Override
    public boolean interpret(Context ctx) {
    
    
        return value;
    }

    /** 检验两个表达式在结构上是否相同 */
    @Override
    public boolean equals(Object o) {
    
    
        if (o != null && o instanceof Constant) {
    
    
            return this.value = ((Constant)o).value;
        }
        return false;
    }

    /** 返回表达式的hashCode */
    @Override
    public int hashCode() {
    
    
        return (this.toString()).hashCode();
    }

    /** 将表达式转换为字符串 */
    @Override
    public String toString(){
    
    
        return new Boolean(value).toString();
    }
}

A Variable object represents a named variable

public class Variable extends Expression {
    
    

    private String name;

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

    /** 解释操作 */
    @Override
    public boolean interpret(Context ctx) {
    
    
        return ctx.lookup(this);
    }

    /** 检验两个表达式在结构上是否相同 */
    @Override
    public boolean equals(Object o) {
    
    
        if (o != null && o instanceof Variable) {
    
    
            return this.name.equals(((Variable)o).name);
        }
        return false;
    }

    /** 返回表达式的hashCode */
    @Override
    public int hashCode() {
    
    
        return (this.toString()).hashCode();
    }

    /** 将表达式转换为字符串 */
    @Override
    public String toString() {
    
    
        return name;
    }
}

Non-terminal expression role:
Insert picture description here
represents the operation of giving a new Boolean expression by logical AND operation of two Boolean expressions:

public class And extends Expression {
    
    

    private Expression left, right;

    public And(Expression left, Expression right) {
    
    
        this.left = left;
        this.right = right;
    }

    /** 解释操作 */
    @Override
    public boolean interpret(Context ctx) {
    
    
        return left.interpret(ctx) && right.interpret(ctx);
    }

    /** 检验两个表达式在结构上是否相同 */
    @Override
    public boolean equals(Object o) {
    
    
        if (o != null && o instanceof And) {
    
    
            return this.left.equals(((And)o).left) && this.right.equals(((And)o).right);
        }
        return false;
    }

    /** 返回表达式的hashCode */
    @Override
    public int hashCode() {
    
    
        return (this.toString()).hashCode();
    }

    /** 将表达式转换为字符串 */
    @Override
    public String toString() {
    
    
        return "(" + left.toString() + " AND " + right.toString() + ")";
    }
}

Represents the operation of giving a new Boolean expression by logical OR operation by two Boolean expressions:

public class Or extends Expression {
    
    

    private Expression left, right;

    public Or(Expression left, Expression right) {
    
    
        this.left = left;
        this.right = right;
    }

    /** 解释操作 */
    @Override
    public boolean interpret(Context ctx) {
    
    
        return left.interpret(ctx) || right.interpret(ctx);
    }

    /** 检验两个表达式在结构上是否相同 */
    @Override
    public boolean equals(Object o) {
    
    
        if (o != null && o instanceof Or) {
    
    
            return this.left.equals(((Or)o).left) && this.right.equals(((Or)o).right);
        }
        return false;
    }

    /** 返回表达式的hashCode */
    @Override
    public int hashCode() {
    
    
        return (this.toString()).hashCode();
    }

    /** 将表达式转换为字符串 */
    @Override
    public String toString() {
    
    
        return "(" + left.toString() + " OR " + right.toString() + ")";
    }
}

Represents the operation of a new Boolean expression given by a Boolean expression through logical negation:

public class Not extends Expression {
    
    

    private Expression exp;

    public Not(Expression exp) {
    
    
        this.exp = exp;
    }

    /** 解释操作 */
    @Override
    public boolean interpret(Context ctx) {
    
    
        return !exp.interpret(ctx);
    }

    /** 检验两个表达式在结构上是否相同 */
    @Override
    public boolean equals(Object o) {
    
    
        if (o != null && o instanceof Not) {
    
    
            return this.exp.equals(((Not)o).exp);
        }
        return false;
    }

    /** 返回表达式的hashCode */
    @Override
    public int hashCode() {
    
    
        return (this.toString()).hashCode();
    }

    /** 将表达式转换为字符串 */
    @Override
    public String toString() {
    
    
        return "(Not " + exp.toString() + ")";
    }
}

The environment class defines a mapping from variables to boolean values:

public class Context {
    
    

    private HashMap map = new HashMap();

    public void assign(Variable var, boolean value) {
    
    
        map.put(var, new Boolean(value));
    }

    public boolean lookup(Variable var) {
    
    
        Boolean value = (Boolean) map.get(var);
        if (value == null) {
    
    
            throw  new IllegalArgumentException();
        }
        return value.booleanValue();
    }
}

Client role:

public class Client {
    
    
    private static Context ctx;
    private static Expression exp;

    public static void main(String[] args) {
    
    
        ctx = new Context();
        Variable x = new Variable("x");
        Variable y = new Variable("y");
        Constant c = new Constant(true);
        ctx.assign(x, false);
        ctx.assign(y, true);
        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));
    }
}

Insert picture description here

Applicable situation

  • The system has a simple language to explain
  • Some recurring problems can be expressed in this simple language
  • Efficiency is not the main consideration

Guess you like

Origin blog.csdn.net/qq_34365173/article/details/108559975