设计模式 行为型模式 实例 -- 解释器模式实例:实现四则运算的计算器

Posted CodeJiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式 行为型模式 实例 -- 解释器模式实例:实现四则运算的计算器相关的知识,希望对你有一定的参考价值。

01:设计模式 行为型模式 – 解释器模式
02:设计模式 行为型模式 实例 – 解释器模式实例:实现四则运算的计算器

1. 解释器模式实例


1.1 需求

请用解释器模式实现一个四则混合运算的表达式解析并结算出表达式的值
例如:5+3-2*6

1.2 类图分析:


1.3 代码实现:


1.3.1 Node:抽象表达式类

package ex08.interpreter;

/**
 * ClassName: Node
 * Description: 抽象表达式类
 *
 * @author Tianjiao
 * @date 2021/11/22 21:29
 */
public abstract class Node 
    public abstract double interpret();


1.3.2 ValueNode:终结符表达式

package ex08.interpreter;

/**
 * ClassName: ValueNode
 * Description: 终结符表达式:封装数值
 *
 * @author Tianjiao
 * @date 2021/11/22 21:31
 */
public class ValueNode extends Node 
    private final String value;

    public ValueNode(String value) 
        this.value = value;
    

    @Override
    public double interpret() 
        return Double.parseDouble(value);
    


1.3.3 AddNode、SubNode、MulNode、DivNode:非终结符表达式

AddNode:

package ex08.interpreter.operator;

import ex08.interpreter.Node;

/**
 * ClassName: AddNode
 * Description:非终结符表达式: 加法
 *
 * @author Tianjiao
 * @date 2021/11/22 21:34
 */
public class AddNode extends Node 
    private final Node leftNode;
    private final Node rightNode;

    public AddNode(Node leftNode, Node rightNode) 
        this.leftNode = leftNode;
        this.rightNode = rightNode;
    

    @Override
    public double interpret() 
        return leftNode.interpret() + rightNode.interpret();
    

SubNode:

package ex08.interpreter.operator;

import ex08.interpreter.Node;

/**
 * ClassName: SubNode
 * Description:非终结符表达式: 减法
 *
 * @author Tianjiao
 * @date 2021/11/22 21:34
 */
public class SubNode extends Node 
    private final Node leftNode;
    private final Node rightNode;

    public SubNode(Node leftNode, Node rightNode) 
        this.leftNode = leftNode;
        this.rightNode = rightNode;
    

    @Override
    public double interpret() 
        return leftNode.interpret() - rightNode.interpret();
    

MulNode:

package ex08.interpreter.operator;

import ex08.interpreter.Node;

/**
 * ClassName: MulNode
 * Description:非终结符表达式: 乘法
 *
 * @author Tianjiao
 * @date 2021/11/22 21:35
 */
public class MulNode extends Node 
    private final Node leftNode;
    private final Node rightNode;

    public MulNode(Node leftNode, Node rightNode) 
        this.leftNode = leftNode;
        this.rightNode = rightNode;
    

    @Override
    public double interpret() 
        return leftNode.interpret() * rightNode.interpret();
    

DivNode :

package ex08.interpreter.operator;

import ex08.interpreter.Node;

/**
 * ClassName: DivNode
 * Description:非终结符表达式: 除法
 *
 * @author Tianjiao
 * @date 2021/11/22 21:36
 */
public class DivNode extends Node 
    private final Node leftNode;
    private final Node rightNode;

    public DivNode(Node leftNode, Node rightNode) 
        this.leftNode = leftNode;
        this.rightNode = rightNode;
    

    @Override
    public double interpret() 
        return leftNode.interpret() / rightNode.interpret();
    


1.3.4 Context:环境类

package ex08.interpreter;

/**
 * ClassName: Context
 * Description: 环境类
 *
 * @author Tianjiao
 * @date 2021/11/22 21:45
 */

import ex08.interpreter.operator.AddNode;
import ex08.interpreter.operator.DivNode;
import ex08.interpreter.operator.MulNode;
import ex08.interpreter.operator.SubNode;

import java.util.Map;
import java.util.Stack;

public class Context 

    private final String context;

    private Node expression;

    public void setExpression(Node expression) 
        this.expression = expression;
    

    Stack<Node> stack = new Stack<>();
    Stack<String> operation = new Stack<>();

    private final Map<String, Integer> level;

    public Context(String context, Map<String, Integer> level) 
        this.context = context;
        this.level = level;
    

    /**
     * 通过解析原始算法字符串,决定操作符栈中运算符优先级
     */
    public void analysis() 
        char[] origin = context.toCharArray();

        for (int i = 0; i < origin.length; i++) 
            if (origin[i] != '+' && origin[i] != '-' && origin[i] != '*' && origin[i] != '/') 
                stack.push(new ValueNode(String.valueOf(origin[i])));
             else 
                if (operation.empty()) 
                    operation.push(String.valueOf(origin[i]));
                 else 
                    combine(String.valueOf(origin[i]));
                
            
        
    

    /**
     * 判断操作符优先级
     *
     * @param left  操作符
     * @param right 操作符
     */
    private boolean compare(String left, String right) 
        return level.get(left) > level.get(right);
    

    /**
     * 递归判断新加入操作符栈中新加入的操作符应该处于的位置,保证优先级高的操作符位于栈顶
     */
    private void combine(String curopt) 
        // peek方法返回栈顶元素但是不移除它
        if (compare(curopt, operation.peek())) 
            operation.push(curopt);
         else 
            Node right = stack.pop();
            Node left = stack.pop();
            switch (operation.pop()) 
                case "*":
                    stack.push(new MulNode(left, right));
                    break;
                case "/":
                    stack.push(new DivNode(left, right));
                    break;
                case "-":
                    stack.push(new SubNode(left, right));
                    break;
                default:
                    stack.push(new AddNode(left, right));
                    break;
            
            combine(curopt);
        
    

    /**
     * 分别取出操作符栈中操作符,和数值栈中的两个操作数进行组合计算,最终得到唯一的结果
     */
    public Node getExpression() 
        while (!operation.empty()) 
            switch (operation.pop()) 
                case "/":
                    Node right = stack.pop();
                    Node left = stack.pop();
                    expression = new DivNode(left, right);
                    stack.push(expression);
                    break;
                case "*":
                    expression = new MulNode(stack.pop(), stack.pop());
                    stack.push(expression);
                    break;
                case "-":
                    Node rightNode = stack.pop();
                    Node leftNode = stack.pop();
                    expression = new SubNode(leftNode, rightNode);
                    stack.push(expression);
                    break;

                default:
                    expression = new AddNode(stack.pop(), stack.pop());
                    stack.push(expression);
                    break;
            
        
        return stack.peek();

    

    public void execute() 
        analysis();
        expression = getExpression();
    


1.3.5 Client:客户端类

package ex08.interpreter;

import java.util.HashMap;

/**
 * ClassName: Client
 * Description: 客户端类:测试类
 *
 * @author Tianjiao
 * @date 2021/11/22 21:48
 */
public class Client 
    public static void main(String[] args) 
        HashMap<String, Integer> operationLevel = new HashMap<>();
        operationLevel.put("+", 1);
        operationLevel.put("-", 2);
        operationLevel.put("*", 3);
        operationLevel.put("/", 4);
        String expression = "5+3-2*6";
        Context context = new Context(expression, operationLevel);
        context.execute();
        System.out.println(context.getExpression().interpret());
    


1.3.6 运行结果:



以上是关于设计模式 行为型模式 实例 -- 解释器模式实例:实现四则运算的计算器的主要内容,如果未能解决你的问题,请参考以下文章

行为型模式之解释器模式

设计模式 行为型模式 实例 -- 备忘录模式实例:游戏备忘录

设计模式 行为型模式 实例 -- 迭代器模式实例:迭代数组

Java设计模式之十一种行为型模式(附实例和详解)

设计模式

Leetcode-设计模式-行为型模式