03-JAVA设计模式-解析器模式

发布于:2024-04-25 ⋅ 阅读:(69) ⋅ 点赞:(0)

解释器模式

什么是解析器模式

在Java中,解释器模式(Interpreter Pattern)是一种行为设计模式,它给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。解释器模式主要用于处理包含特定语法规则的简单语言,如数学表达式、SQL语句、配置文件等。

解释器模式主要由以下角色组成:

  • 抽象表达式(Abstract Expression): 声明一个解释操作的接口,这个接口叫做解释操作。
  • 终结符表达式(Terminal Expression): 实现抽象表达式接口,该接口表示处理解释器语法中出现的终结符,终结符是语法中不可再分的最小单位。
  • 非终结符表达式(Nonterminal Expression): 同样实现抽象表达式接口,该接口表示处理解释器语法中出现的非终结符,非终结符是语法中的短语或句子,一般由终结符构成。
  • 环境角色(Context): 包含解释器之外的全局信息,一般是用来存储有关被解释句子的信息,如符号表的值等。
  • 客户端(Client): 构建(或给定)表示该文法的抽象语法树,并调用解释器的解释方法来执行程序。

注意:

解析器模式是一种不常用的设计模式

用于描述如何构成已个简单的语言解释器,主要用于使用面相对象语言开发编译器和解释器设计

当我们需要开发一种新的语言是,可以考虑使用

实际开发中尽量不要使用解释器模式,后期维护忽悠很大的麻烦,在项目中,可以使用Jruby,Groovy,java的js引擎来替代解释器的作用,弥补java语言的不足

案例

实现通过输入字符串10+30-25计算得到最终的结果

UML

在这里插入图片描述

实现步骤:

  • 定义解释接口及返回值Expression
  • 创建具体的表达式-数字NumberExpression
  • 创建具体的表达式-符号OperatorExpression
  • 创建具体的表达式-加法AddExpression
  • 创建具体的表达式-减法SubtractionExpression
  • 创建解析类ExpressionParser,实现表达式解析,且用队列存储解析后的表达式,提供interpret()方法执行表达式

实现代码

Expression.java

// 抽象表达式接口
public interface Expression {
    // 定义解释接口及返回值
    int interpret();
}

NumberExpression.java

// 具体的表达式-数字
public class NumberExpression implements Expression{
    // 定义接收值
    private Integer value;
    public NumberExpression(Integer value) {
        this.value = value;
    }
    @Override
    public int interpret() {
        return value;
    }
}

OperatorExpression.java

// 具体的表达式-符号
public class OperatorExpression implements Expression{
    // 定义接收值
    private char value;
    public OperatorExpression(char value) {
        this.value = value;
    }
    @Override
    public int interpret() {
        return value;
    }
}

AddExpression.java

// 具体的表达式-加法
public class AddExpression implements Expression{
    // 解析器左侧表达式
    private Expression left;
    // 解析器右侧表达式
    private Expression right;
    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public int interpret() {
        return left.interpret() + right.interpret();
    }
}

Expression.java

// 具体的表达式-减法
public class SubtractionExpression implements Expression{
    // 解析器左侧表达式
    private Expression left;
    // 解析器右侧表达式
    private Expression right;
    public SubtractionExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public int interpret() {
        return left.interpret() - right.interpret();
    }
}

ExpressionParser.java

import java.util.ArrayDeque;
import java.util.Deque;

// 解析器类
public class ExpressionParser{
    private String expression;
    private int index = 0;
    private Deque<Expression> queue = new ArrayDeque<Expression>();

    public ExpressionParser(String expression) {
        this.expression = expression;
        parse();
    }

    // 解析表达式
    public void parse(){
        // 判断是否连续数字
        boolean markDigit = false;
        // 判断是否连续运算符
        boolean markOperation = false;
        while (index < expression.length()){
            char c = expression.charAt(index);
            // 字符判断
            if(Character.isDigit(c) && !markDigit){
                markDigit = true;
                markOperation = false;
                parseNumber();
                continue;
            }
            else if((c == '+' || c == '-') && !markOperation){
                markDigit = false;
                markOperation = true;
                parseOperation();
            } else {
                throw new RuntimeException("输入字符错误: " + c);
            }
            index++;
        }
    }

    // 解析数字
    private void parseNumber() {
        StringBuilder sb = new StringBuilder();
        while (index < expression.length() && Character.isDigit(expression.charAt(index))) {
            sb.append(expression.charAt(index));
            index++;
        }
        int number = Integer.parseInt(sb.toString());
        queue.offer(new NumberExpression(number));
    }

    // 解析符号
    private void parseOperation() {
        queue.offer(new OperatorExpression(expression.charAt(index)));
    }

    // 计算
    public int interpret() {
        Expression result = null;
        int len = queue.size();
        for (int i = 0; i < len; i++) {
            Expression pop = queue.poll();
            if(result == null){
                result = pop;
            }
            else if (pop instanceof OperatorExpression &&  pop.interpret() == '+') {
                result = new AddExpression(result, queue.poll());
                i++;
            }
            else if (pop instanceof OperatorExpression &&  pop.interpret() == '-') {
                result = new SubtractionExpression(result, queue.poll());
                i++;
            }
            else {
                throw new RuntimeException("表达式异常");
            }
        }
        return result.interpret();
    }
}

TestClient.java

// 测试
public class TestClient {
    public static void main(String[] args) {
        String expression = "10+30-25";
        ExpressionParser parser = new ExpressionParser(expression);
        System.out.println("Result: " + parser.interpret());
    }
}

执行结果:

在这里插入图片描述

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git


网站公告

今日签到

点亮在社区的每一天
去签到