设计模式(22):解释器模式

时间:2024-04-10 18:25:36

解释器

  • 是一种不常用的设计模式
  • 用于描述如何构成一个简单的语言解释器,主要用于使用面向对象语言开发的解释器和解释器设计
  • 当我们需要开发一种新的语言时,可以考虑使用解释器模式
  • 尽量不要使用解释器模式,后期维护会有很大麻烦。在项目中,可以使用jruby、groovy、java的js引擎来替代解释器的作用,弥补java语言的不足。

开发中常见的场景

  • EL表达式的处理
  • 正则表达式解释器
  • SQL语法的解释器
  • 数学表达式解释器

举例代码实现

  • 解析和执行数学表达式
    输入"5+4*5-8/4",输出“23”
  • 抽象解释器接口
/**
 * 抽象解释器接口
 */
public interface Expression {
	int interpret(Context context);
}
  • 终结符表达式
/**
 * 数值表达式---终结符表达式
 */
public class NumberExpression implements Expression{
	private Integer number;
	public NumberExpression(Integer number) {
		super();
		this.number = number;
	}
	@Override
	public int interpret(Context context) {
		return number;
	}
}
/**
 * 运算符号表达式---终结符表达式
 * 	symbol:
 * 		1:加 
 * 		2:减 
 * 		3:乘 
 * 		4:除 
 */
public class SymbolExpression implements Expression {
	private int symbol;	
	public SymbolExpression(int symbol) {
		super();
		this.symbol = symbol;
	}
	@Override
	public int interpret(Context context) {
		return symbol;
	}
}
  • 非终结符表达式
/**
 * 加法表达式——加法表达式也是数值表达式的一种
 */
public class AdditionExpression extends NumberExpression{
	private NumberExpression left;
	private NumberExpression right;
	public AdditionExpression(NumberExpression left, NumberExpression right) {
		super(1);
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		return left.interpret(context) + right.interpret(context);
	}
}
/**
 * 减法表达式---减法表达式也是数值表达式的一种
 */
public class SubtractExpression extends NumberExpression{
	private NumberExpression left;
	private NumberExpression right;
	public SubtractExpression(NumberExpression left, NumberExpression right) {
		super(2);
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		return left.interpret(context) - right.interpret(context);
	}
}
/**
 * 乘法表达式——乘法表达式也是数值表达式的一种
 */
public class MultiplicationExpression extends NumberExpression{
	private NumberExpression left;
	private NumberExpression right;
	public MultiplicationExpression(NumberExpression left, NumberExpression right) {
		super(3);
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		return left.interpret(context) * right.interpret(context);
	}
}
/**
 * 除法表达式——除法表达式也是数值表达式的一种
 */
public class DivisionExpression extends NumberExpression{
	private NumberExpression left;
	private NumberExpression right;
	public DivisionExpression(NumberExpression left, NumberExpression right) {
		super(4);
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		return left.interpret(context) / right.interpret(context);
	}
}
  • 上下文类(context)
public class Context {
	
	private Expression expression;
	
	public Context(String expression) {
		LinkedList<Expression> linkedList = new LinkedList<Expression>();
		int num = 0;
		for(int i=0;i<expression.length();i++) {
			char ati;
			if((ati=expression.charAt(i))>='0' && ati<='9') {
				num = num*10 + (ati-'0');
			}else {
				Expression peek;
				SymbolExpression symbol;
				NumberExpression left,right;
				if(!linkedList.isEmpty() && (
					(peek=linkedList.peekLast()) instanceof SymbolExpression) 
					&& (peek.interpret(this)==3 || peek.interpret(this)==4)
					){
					symbol = (SymbolExpression)linkedList.pollLast();
					left = (NumberExpression)linkedList.pollLast();
					right = new NumberExpression(num);
					if(symbol.interpret(this)==3){
						linkedList.addLast(new MultiplicationExpression(left, right));
					}else{
						linkedList.addLast(new DivisionExpression(left, right));
					}
				}else{
					linkedList.addLast(new NumberExpression(num));
				}
				SymbolExpression symbolExpression = null;
				switch (ati) {
				case '+':
					symbolExpression = new SymbolExpression(1);
					break;
				case '-':
					symbolExpression = new SymbolExpression(2);
					break;
				case '*':
					symbolExpression = new SymbolExpression(3);
					break;
				case '/':
					symbolExpression = new SymbolExpression(4);
					break;
				default:
					break;
				}
				num = 0;
				linkedList.addLast(symbolExpression);
			}
		}
		Expression peek;
		if(!linkedList.isEmpty() &&(	
				(peek=linkedList.peekLast()) instanceof SymbolExpression) 
					&& (peek.interpret(this)==3 || peek.interpret(this)==4)
		 	){
			Expression symbol = linkedList.pollLast();
			NumberExpression left = (NumberExpression)linkedList.pollLast();
			NumberExpression right = new NumberExpression(num);
			if(symbol.interpret(this)==3){
				linkedList.addLast(new MultiplicationExpression(left, right));
			}else{
				linkedList.addLast(new DivisionExpression(left, right));
			}
		}else{
			linkedList.add(new NumberExpression(num));
		}
		init(linkedList);
	}
	private void init(LinkedList<Expression> linkedList){
		SymbolExpression symbolExpression = null;
		NumberExpression left = null;
		while(!linkedList.isEmpty()){
			Expression tempExpression = linkedList.pollFirst();
			if(tempExpression instanceof SymbolExpression){
				symbolExpression = (SymbolExpression)tempExpression;
			}else{
				if(left==null){
					left = (NumberExpression)tempExpression;
				}else{
					NumberExpression right = (NumberExpression)tempExpression;
					switch (symbolExpression.interpret(this)) {
					case 1:
						left = new AdditionExpression(left, right);
						break;
					case 2:
						left = new SubtractExpression(left, right);
						break;
					case 3:
						left = new MultiplicationExpression(left, right);
						break;
					case 4:
						left = new DivisionExpression(left, right);
						break;
					default:
						break;
					}
				}
			}
		}
		this.expression = left;
	}
	public int calculate(){
		return this.expression.interpret(this);
	}
}
  • 客户端调用
public static void main(String[] args) {
	Context context = new Context("33+12*9+42/2+6/3");
	int calculate = context.calculate();
	System.out.println(calculate);
}
  • 结果
    在这里插入图片描述





更多设计模式学习:

          设计模式(1):介绍
          设计模式(2):单例模式
          设计模式(3):工厂模式
          设计模式(4):建造者模式
          设计模式(5):原型模式
          设计模式(6):桥接模式
          设计模式(7):装饰器模式
          设计模式(8):组合模式
          设计模式(9):外观模式
          设计模式(10):享元模式
          设计模式(11):适配器模式
          设计模式(12):代理模式
          设计模式(13):模板方法模式
          设计模式(14):命令模式
          设计模式(15):迭代器模式
          设计模式(16):观察者模式
          设计模式(17):中介者模式
          设计模式(18):状态模式
          设计模式(19):策略模式
          设计模式(20):责任链模式
          设计模式(21):备忘录模式
          设计模式持续更新中…