解释器模式

一、解释器模式

1、定义

解释器模式(Interpreter Pattern)指给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子,属于行为型设计模式。

解释器模式是一种按照规定的文法(语法)进行解析的模式。其核心思想就是识别文法,构建解释。

2、结构

(1)模式的结构

主要角色如下:

  • 抽象表达式(IExpression):负责定义一个解释方法 interpret,交由具体子类进行具体解释。
  • 终结符表达式(TerminalExpression):实现文法中与终结符有关的解释操作。通常一个解释器中只有- 一个终结符表达式,但有多个实例,对应不同的终结符。
  • 非终结符表达式(NonterminalExpression):实现文法中与非终结符有关的解释操作。
  • 上下文环境类(Context):包含解释器之外的全局信息。它一般用来存放文法中各个终结符所对应的具体值。

3、优缺点

优点:

  • 由于语法由很多类表示,所以,当语法规则或者扩展语法时,只需要修改或者扩展表达式即可。
  • 对于简单的文法应当比较简单且易于实现,过于复杂的语法并不适合解释器模式。

缺点:

  • 由于语法由很多类表示,过于复杂时,会产生大量的解释类,引起类臃肿,增加系统维护的难度。
  • 解释器模式采用递归调用方法,当完整表达式层级较深时,解释效率会下降。

4、使用场景

  • 一些重复出现的问题可以用一种简单的语言进行表达。
  • 一个简单语法需要解释的场景。

5、在框架源码中使用

  • JDK源码中的 Pattern对正则表达式的编译和解析。
  • Spring源码中的 ExpressionParser接口。

二、模式的应用实例

使用解释器模式来简单的实现一个计算器,这里不考虑运算符计算顺序。

(1)抽象表达式

interface IArithmeticInterpreter {
	int interpret();
}

// 数字表达式
class NumberInterpreter implements IArithmeticInterpreter {
	private int value;

	public NumberInterpreter(int value) {
		this.value = value;
	}

	@Override
	public int interpret() {
		return this.value;
	}
}

(2)终结符表达式

abstract class Interpreter implements IArithmeticInterpreter {

	protected IArithmeticInterpreter left;
	protected IArithmeticInterpreter right;

	public Interpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
		this.left = left;
		this.right = right;
	}
}

(3)非终结符表达式

class AddInterpreter extends Interpreter {
	public AddInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
		super(left, right);
	}

	@Override
	public int interpret() {
		return this.left.interpret() + this.right.interpret();
	}
}

class SubInterpreter extends Interpreter {
	public SubInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
		super(left, right);
	}

	@Override
	public int interpret() {
		return this.left.interpret() - this.right.interpret();
	}
}

class MultiInterpreter extends Interpreter {
	public MultiInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
		super(left, right);
	}

	@Override
	public int interpret() {
		return this.left.interpret() * this.right.interpret();
	}
}

class DivInterpreter extends Interpreter {
	public DivInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
		super(left, right);
	}

	@Override
	public int interpret() {
		return this.left.interpret() / this.right.interpret();
	}
}

(4)上下文环境类 - 计算器

class GPCalculator {
	private Stack<IArithmeticInterpreter> stack = new Stack<>();

	public GPCalculator(String expression) {
		this.parse(expression);
	}

	/**
	 * 解析表达式:约定表达式以空格分隔
	 * 
	 * @param expression
	 */
	private void parse(String expression) {
		String[] elements = expression.split(" ");
		IArithmeticInterpreter left, right;

		for (int i = 0; i < elements.length; i++) {
			String operator = elements[i];
			if("+".equals(operator) || "-".equals(operator) || "*".equals(operator) || "/".equals(operator)){
				System.out.println("应用运算符:" + operator);
				left = this.stack.pop();
				right = new NumberInterpreter(Integer.valueOf(elements[++i]));
				System.out.println("出栈:left=" + left.interpret() + ", right=" + right.interpret());

				Interpreter interpreter = null;
				if("+".equals(operator)){
					interpreter = new AddInterpreter(left, right);
				}else if("-".equals(operator)){
					interpreter = new SubInterpreter(left, right);
				}else if("*".equals(operator)){
					interpreter = new MultiInterpreter(left, right);
				}else if("/".equals(operator)){
					interpreter = new DivInterpreter(left, right);
				}else{
					new RuntimeException("不支持该运算符:" + operator);
				}
				this.stack.push(interpreter);
				System.out.println("应用运算符计算结果入栈,result=" + interpreter.interpret());
			}else{
				NumberInterpreter numberInterpreter = new NumberInterpreter(Integer.valueOf(elements[i]));
				this.stack.push(numberInterpreter);
				System.out.println("入栈:" + numberInterpreter.interpret());
			}
		}
	}

	// 获取计算结果
	public int calculate() {
		return this.stack.pop().interpret();
	}

}

(5)测试

	public static void main(String[] args) {
		GPCalculator gpCalculator = new GPCalculator("2 + 3");
		System.out.println("2 + 3 = "+ gpCalculator.calculate());

		System.out.println("-------------");
		GPCalculator gpCalculator2 = new GPCalculator("2 * 3");
		System.out.println("2 * 3 = "+ gpCalculator2.calculate());

		System.out.println("-------------");
		GPCalculator gpCalculator3 = new GPCalculator("2 + 3 - 1");
		System.out.println("2 + 3 - 1 = "+ gpCalculator3.calculate());
	}

在这里插入图片描述

– 求知若饥,虚心若愚。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值