设计模式之--解释器模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiao__jia__jia/article/details/86777532

                设计模式之--解释器模式

解释器模式原理

大数据统计项目遇到的问题

按照计算模型对现有数据统计、分析、预测

一般的计算模型是一个或多个运算公式,通常是加减乘除四则运算

计算模型需要运行期编辑

设计方案要有高扩展性

思考怎么设计


 

解释器模式原理

计算模型按正常算术方式书写,解释器处理语法逻辑

计算模型里有两类符号:数据和计算符

用逆波兰算法分析算式语法

用解释器模式处理数据


解释器模式:定义一个语法,定义一个解释器,该解释器处理该语法句子
将某些复杂问题 ,表达为某种语法规则,然后构建解释器来解释处理这类句子


解释器模式优缺点

优点:

  容易修改,修改语法规则只要修改相应非终结符即可

  扩展方便,扩展语法,只要增加非终结符类即可

缺点:

  对于复杂语法的表示会产生复杂的类层次结构,不便管理和维护

  解释器采用递归方式,效率会受影响

解释器模式示例代码讲解

示例项目类结构



AbstractExpresstion 

import java.util.HashMap;

public abstract class AbstractExpresstion {
	public abstract Float interpreter(HashMap<String, Float> var);
}


VarExpresstion 

import java.util.HashMap;

public class VarExpresstion extends AbstractExpresstion {
	private String key;

	public VarExpresstion(String _key) {

		this.key = _key;

	}

	@Override
	public Float interpreter(HashMap<String, Float> var) {
		// TODO Auto-generated method stub
		return var.get(this.key);
	}

}


SymbolExpresstion 

import java.util.HashMap;

public abstract class SymbolExpresstion extends AbstractExpresstion {
	protected AbstractExpresstion left;
	protected AbstractExpresstion right;

	public SymbolExpresstion(AbstractExpresstion _left,
			AbstractExpresstion _right) {
		this.left = _left;

		this.right = _right;
	}

}


MultiExpresstion 

import java.util.HashMap;

public class MultiExpresstion extends SymbolExpresstion {

	public MultiExpresstion(AbstractExpresstion _left,
			AbstractExpresstion _right) {
		super(_left, _right);
		// TODO Auto-generated constructor stub
	}

	@Override
	public Float interpreter(HashMap<String, Float> var) {
		// TODO Auto-generated method stub
		return super.left.interpreter(var) * super.right.interpreter(var);
	}

}


DivExpresstion 

import java.util.HashMap;

public class DivExpresstion extends SymbolExpresstion {

	public DivExpresstion(AbstractExpresstion _left, AbstractExpresstion _right) {
		super(_left, _right);
		// TODO Auto-generated constructor stub
	}

	@Override
	public Float interpreter(HashMap<String, Float> var) {
		// TODO Auto-generated method stub
		return super.left.interpreter(var) / super.right.interpreter(var);
	}

}


AddExpresstion 


import java.util.HashMap;

public class AddExpresstion extends SymbolExpresstion {

	public AddExpresstion(AbstractExpresstion _left, AbstractExpresstion _right) {
		super(_left, _right);
		// TODO Auto-generated constructor stub
	}

	@Override
	public Float interpreter(HashMap<String, Float> var) {
		// TODO Auto-generated method stub
		return super.left.interpreter(var) + super.right.interpreter(var);
	}

}


SubExpresstion


import java.util.HashMap;

public class SubExpresstion extends SymbolExpresstion {

	public SubExpresstion(AbstractExpresstion _left, AbstractExpresstion _right) {
		super(_left, _right);
		// TODO Auto-generated constructor stub
	}

	@Override
	public Float interpreter(HashMap<String, Float> var) {
		// TODO Auto-generated method stub
		return super.left.interpreter(var) - super.right.interpreter(var);
	}

}



逆波兰表达式的解析过程
RPN 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Stack;
import java.util.StringTokenizer;

public class RPN {

	private ArrayList<String> expression = new ArrayList<String>();// 存储中序表达式

	private ArrayList<String> right = new ArrayList<String>();// 存储右序表达式

	private AbstractExpresstion result;// 结果

	// 依据输入信息创建对象,将数值与操作符放入ArrayList中
	public RPN(String input) {
		StringTokenizer st = new StringTokenizer(input, "+-*/()", true);
		while (st.hasMoreElements()) {
			expression.add(st.nextToken());
		}
	}

	// 将中序表达式转换为右序表达式
	private void toRight() {
		Stacks aStack = new Stacks();
		String operator;
		int position = 0;
		while (true) {
			if (Calculate.isOperator((String) expression.get(position))) {
				if (aStack.top == -1
						|| ((String) expression.get(position)).equals("(")) {
					aStack.push(expression.get(position));
				} else {
					if (((String) expression.get(position)).equals(")")) {
						if (!((String) aStack.top()).equals("(")) {
							operator = (String) aStack.pop();
							right.add(operator);
						}
					} else {
						if (Calculate.priority((String) expression
								.get(position)) <= Calculate
								.priority((String) aStack.top())
								&& aStack.top != -1) {
							operator = (String) aStack.pop();
							if (!operator.equals("("))
								right.add(operator);
						}
						aStack.push(expression.get(position));
					}
				}
			} else
				right.add(expression.get(position));
			position++;
			if (position >= expression.size())
				break;
		}
		while (aStack.top != -1) {
			operator = (String) aStack.pop();
			right.add(operator);
		}
	}

	// 对右序表达式进行求值
	public void getResult(HashMap<String, Float> var) {
		this.toRight();
		Stack<AbstractExpresstion> stack = new Stack<AbstractExpresstion>();
		AbstractExpresstion op1, op2;
		String is = null;
		Iterator it = right.iterator();

		while (it.hasNext()) {
			is = (String) it.next();
			if (Calculate.isOperator(is)) {
				op2 = stack.pop();
				op1 = stack.pop();
				stack.push(Calculate.twoResult(is, op1, op2));
			} else
				stack.push(new VarExpresstion(is));
		}
		result = stack.pop();
		it = expression.iterator();
		while (it.hasNext()) {
			System.out.print((String) it.next());
		}
		System.out.println("=" + result.interpreter(var));
	}

	public static class Calculate {
		// 判断是否为操作符号
		public static boolean isOperator(String operator) {
			if (operator.equals("+") || operator.equals("-")
					|| operator.equals("*") || operator.equals("/")
					|| operator.equals("(") || operator.equals(")"))
				return true;
			else
				return false;
		}

		// 设置操作符号的优先级别
		public static int priority(String operator) {
			if (operator.equals("+") || operator.equals("-")
					|| operator.equals("("))
				return 1;
			else if (operator.equals("*") || operator.equals("/"))
				return 2;
			else
				return 0;
		}

		// 做2值之间的计算
		public static AbstractExpresstion twoResult(String op,
				AbstractExpresstion a, AbstractExpresstion b) {
			try {

				AbstractExpresstion result = null;
				if (op.equals("+"))
					result = new AddExpresstion(a, b);
				else if (op.equals("-"))
					result = new SubExpresstion(a, b);
				else if (op.equals("*"))
					result = new MultiExpresstion(a, b);
				else if (op.equals("/"))
					result = new DivExpresstion(a, b);
				else
					;
				return result;
			} catch (NumberFormatException e) {
				System.out.println("input has something wrong!");
				return null;
			}
		}
	}

	// 栈类
	public class Stacks {
		private LinkedList list = new LinkedList();
		int top = -1;

		public void push(Object value) {
			top++;
			list.addFirst(value);
		}

		public Object pop() {
			Object temp = list.getFirst();
			top--;
			list.removeFirst();
			return temp;

		}

		public Object top() {
			return list.getFirst();
		}
	}
}



Calculator 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

public class Calculator {

    public Calculator() {
        float[][] dataSource = new float[3][6];
        System.out.println("data source:");
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 6; j++) {
                dataSource[i][j] = (float) (Math.random() * 100);
                System.out.print(dataSource[i][j] + ",");
            }
            System.out.println(";");
        }

        try {
            System.out.println("Input a expression:");
            BufferedReader is = new BufferedReader(new InputStreamReader(
                    System.in));
            for (;;) {
                String input = new String();
                input = is.readLine().trim();
                if (input.equals("q"))
                    break;
                else {
                    RPN boya = new RPN(input);
                    HashMap<String, Float> var;
                    for (int i = 0; i < 3; i++) {
                        var = new HashMap<String, Float>();
                        var.put("a", dataSource[i][0]);
                        var.put("b", dataSource[i][1]);
                        var.put("c", dataSource[i][2]);
                        var.put("d", dataSource[i][3]);
                        var.put("e", dataSource[i][4]);
                        var.put("f", dataSource[i][5]);

                        boya.getResult(var);

                    }

                }
                System.out
                        .println("Input another expression or input 'q' to quit:");
            }
            is.close();
        } catch (IOException e) {
            System.out.println("Wrong input!!!");
        }

    }

}




MainTest



public class MainTest {

	public static void main(String[] args) {

		new Calculator();
	}

}


解释器模式关键点

解释器模式原理
解释器模式:定义一个语法, 定义一个解释器,该解释器处理该语法句子

 

注意事项:

  尽量不要在重要的模块中使用解释器模式

  解释器模式在实际的系统开发中使用的非常少

  可以考虑一下Expression4J、MESP、Jep等开源的解析工具包
 

解释器模式适用场合
 

适用场合:

  当你有一个简单语法,而且效率不是问题的时候

  一些数据分析工具、报表设计工具、科学计算工具等

猜你喜欢

转载自blog.csdn.net/xiao__jia__jia/article/details/86777532