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

解释器

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

开发中常见的场景

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

举例代码实现

  • 解析和执行数学表达式
    输入"5+4*5-8/4",输出"23"
  • 抽象解释器接口
java 复制代码
/**
 * 抽象解释器接口
 */
public interface Expression {
	int interpret(Context context);
}
  • 终结符表达式
java 复制代码
/**
 * 数值表达式---终结符表达式
 */
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;
	}
}
  • 非终结符表达式
java 复制代码
/**
 * 加法表达式------加法表达式也是数值表达式的一种
 */
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)
java 复制代码
public class Context {
	Expression expression;
	public Context(String expression) {
		Expression parse = init(expression);
		this.expression = parse;
	}
	public int calculate(){
		return this.expression.interpret(this);
	}
	private Expression init(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 {
				addNum(linkedList, 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);
			}
		}
		addNum(linkedList, num);
		return getExpression(linkedList);
	}
	/**
	 * 添加num
	 * @param linkedList
	 * @param num
	 */
	private void addNum(LinkedList<Expression> linkedList,int num) {
		NumberExpression numberExpression = new NumberExpression(num);
		if(!linkedList.isEmpty()) {
			Expression symbol = linkedList.pollLast();
			if(symbol.interpret(this)==1 || symbol.interpret(this)==2) {
				linkedList.addLast(symbol);
			}else {
				NumberExpression left = (NumberExpression)linkedList.pollLast();
				NumberExpression right = numberExpression;
				if(symbol.interpret(this)==3) {
					numberExpression = new MultiplicationExpression(left, right);
				}else {
					numberExpression = new DivisionExpression(left, right);
				}
			}
		}
		linkedList.add(numberExpression);
	}
	/**
	 * 获取Expression
	 * @param linkedList
	 * @return
	 */
	private Expression getExpression(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;
					}
				}
			}
		}
		return left;
	}
}			
  • 客户端调用
java 复制代码
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:"+calculate);
}
  • 结果

更多设计模式学习:

设计模式(1):介绍

设计模式(2):单例模式

设计模式(3):工厂模式

设计模式(4):建造者模式

设计模式(5):原型模式

设计模式(6):桥接模式

设计模式(7):装饰器模式

设计模式(8):组合模式

设计模式(9):外观模式

设计模式(10):享元模式

设计模式(11):适配器模式

设计模式(12):代理模式

设计模式(13):模板方法模式

设计模式(14):命令模式

设计模式(15):迭代器模式

设计模式(16):观察者模式

设计模式(17):中介者模式

设计模式(18):状态模式

设计模式(19):策略模式

设计模式(20):责任链模式

设计模式(21):备忘录模式

设计模式持续更新中...

相关推荐
缺点内向2 小时前
Java:创建、读取或更新 Excel 文档
java·excel
带刺的坐椅2 小时前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看4 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程4 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t4 小时前
ZIP工具类
java·zip
lang201509284 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan5 小时前
第10章 Maven
java·maven
百锦再6 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说6 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多6 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring