[设计模式] - 解释器模式

一、解释器模式简介

1. 什么是解释器模式

解释器模式(Interperter ) 属于行为型设计模式的一种,是一种按照规定语法进行解析的方案。其定义为:Given a language ,define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language (给定一门语言,定义一种语法规则并提供对应的解释器,该解释器用来解释语法中的语句) 。解释器模式在实际开发中很少用到,大多数情况下我们都是直接使用解释器模式的实现,比如正则表达式,cron表达式等等。

2. 业务场景

Java语言在设计时已经实现了很多我们日常需求中常用的表达式,但是有一些冷门的数学运算表达式他并没有直接在JDK中提供支持。比如我们高中数学中学到的阶乘。

阶乘是基斯顿·卡曼(Christian Kramp,1760~1826)于 1808 年发明的运算符号,是数学术语。
一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。1808年,基斯顿·卡曼引进这个表示法。
亦即n!=1×2×3×…×(n-1)×n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。

那么今天我们就通过实现一个阶乘计算器的方式来讲述一下解释器模式的日常应用。
在这里插入图片描述

二、解释器模式的实现

1. 设计思路

在我们进行代码实现前,我们首先要制定一个简单的计算流程图:
在这里插入图片描述
接下来我们要分析一下在这个流程中一共有多少角色参与了运算:

  1. 抽象解释器(AbstractExpression) : 具体的解释任务交由子类完成,具体的解释器由终结符表达式和非终结符表达式完成。
  2. 终结符表达式 (TerminalExpression):负责实现语句中非运算符号元素的逻辑处理。
  3. 非终结符表达式(NonterminalExpression):负责运算指令中运算符相关元素的逻辑处理。
  4. 运算指令(Context):负责存储运算指令(表达式)。

ok,解析来请看代码实现:

2. 解释器模式的代码实现

1. 我们先创建一个抽象解释器

public interface Expression {
	Integer interpret();
}

2. 接下来我们先实现一个终结符表达式

public class NumberExpression implements Expression {

	private Integer number;

	public NumberExpression(Integer number) {
		super();
		this.number = number;
	}

	@Override
	public Integer interpret() {
		// TODO Auto-generated method stub
		return number;
	}

}

3. 然后我们再实现一个非终结符表达式

public class FactorialExpression implements Expression {
	
	private Expression expression;
	private Integer result; 

	public FactorialExpression(Expression expression) {
		super();
		this.expression = expression;
	}

	@Override
	public Integer interpret() {
		result = expression.interpret();
		
		for (int i = result-1; i > 1; i--) {
			result *= i;
		}
		return result;
	}
}

4. 然后我们做一个阶乘计算器

public class Calculator {

	private Expression expression;

	public Calculator(String expStr) {
		Stack<Expression> stack = new Stack<>();
		char[] charArray = expStr.toCharArray();
		for (char c : charArray) {
			if ("!".equals(String.valueOf(c))) {
				Expression pop = stack.pop();
				expression = new FactorialExpression(pop);
			} else {
				NumberExpression numberExpression = new NumberExpression(Character.getNumericValue(c));
				stack.push(numberExpression);
			}
		}
	}

	public Integer execute() {
		return expression.interpret();
	}

}

测试代码:

public class Client {

	public static void main(String[] args) {
		String expStr = "8!";
		Calculator calculator = new Calculator(expStr);
		Integer result = calculator.execute();
		System.out.println(expStr + "的运算结果为:" + result);

	}

}

测试结果:
在这里插入图片描述

3. 解释器模式的类图设计

在这里插入图片描述

三、解释器模式总结

1. 解释器模式的特点

优点:

  1. 可拓展性强

缺点:

  1. 会造成类的膨胀
  2. 增加系统的复杂性
  3. 效率低

2. 解释器模式的使用场景

  1. 可以将一个需要解释执行的语句表示为一个抽象语法树
  2. 重发发生的问题

3. 注意

请不要再重要的模块中使用解释器模式,这样会造成后期维护非常困难,在项目中我们可以尽量使用脚本语言(如 shell ,JRuby,Groovy等)来弥补Java语言设计的不足。

四、结语

今天的代理模式讲解就全部结束了,设计模式的相关代码已经在gitee上收录,有需求的小伙伴可以直接拿走:

https://gitee.com/xiaolong-oba/csdn-learning-code.git

有疑问的小伙伴欢迎评论区留言或者私信博主,博主会在第一时间为你解答。
码字不易,感到有收获的小伙伴记得要关注博主一键三连,不要当白嫖怪哦~
博主在这里祝大家可以在新的一年升职加薪,走上人生巅峰!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓龙oba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值