设计模式 | 飞机票 |
---|---|
三大工厂模式 | 登机入口 |
策略模式 | 登机入口 |
委派模式 | 登机入口 |
模板方法模式 | 登机入口 |
观察者模式 | 登机入口 |
单例模式 | 登机入口 |
原型模式 | 登机入口 |
代理模式 | 登机入口 |
装饰者模式 | 登机入口 |
适配器模式 | 登机入口 |
建造者模式 | 登机入口 |
责任链模式 | 登机入口 |
享元模式 | 登机入口 |
组合模式 | 登机入口 |
门面模式 | 登机入口 |
桥接模式 | 登机入口 |
中介者模式 | 登机入口 |
迭代器模式 | 登机入口 |
状态模式 | 登机入口 |
解释器模式 | 登机入口 |
备忘录模式 | 登机入口 |
命令模式 | 登机入口 |
访问者模式 | 登机入口 |
软件设计7大原则和设计模式总结 | 登机入口 |
解释器模式从字面上来理解就是需要去解释某些内容的含义,而实际上这也正是解释器模式的作用。本文主要会介绍解释器模式的原理,并会结合一个简单的示例来加深我们对解释器模式的理解,解释器模式在我们的应用开发层已经有了很多轮子,所以我们也比较少再去重造轮子。
解释器模式(Interpreter Pattern)是指给定一门语言,定义它的文法的一种表示(如:加减乘除表达式和正则表达式等),然后再定义一个解释器,该解释器用来解释我们的文法表示(表达式)。
解释器模式是一种按照规定的语法(文法)来进行解析的一种设计模式,属于行为型模式。
好了,装逼时刻又到了:Talk is cheap,Show you the code,先看一个非常简单的例子。
在解释器模式中有终结符表达式和非终结符表达式这两个概念。
下面我们就以简单的加减法表达式类简单写一个示例:
1、首先建立一个顶层的表达式接口:
package com.zwx.design.pattern.interpreter;
public interface IExpression {
int interpret();
}
2、定义一个抽象的非终结表达式(比如加号和减号这种就属于非终结表达式):
package com.zwx.design.pattern.interpreter;
/**
* 非终结表达式-抽象表达式
*/
public abstract class AbstractNonTerminalExpression implements IExpression{
protected IExpression leftExpression;
protected IExpression rightExpression;
public AbstractNonTerminalExpression(IExpression leftExpression, IExpression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
}
3、因为本次示例中只列举加法和减法,所以我们还需要一个加法类和一个减法类:
package com.zwx.design.pattern.interpreter;
/**
* 非终结表达式-具体表达式-加法表达式
*/
public class AddExpression extends AbstractNonTerminalExpression {
public AddExpression(IExpression leftExpression, IExpression rightExpression) {
super(leftExpression, rightExpression);
}
@Override
public int interpret() {
return this.leftExpression.interpret() + this.rightExpression.interpret();
}
}
package com.zwx.design.pattern.interpreter;
/**
* 非终结表达式-具体表达式-减法表达式
*/
public class SubExpression extends AbstractNonTerminalExpression {
public SubExpression(IExpression leftExpression, IExpression rightExpression) {
super(leftExpression, rightExpression);
}
@Override
public int interpret() {
return this.leftExpression.interpret() - this.rightExpression.interpret();
}
}
4、再建立一个终结表达式(如加减法运算中的数值):
package com.zwx.design.pattern.interpreter;
/**
* 终结表达式-数值表达式
*/
public class NumberExpression implements IExpression{
private int value;
public NumberExpression(String value) {
this.value = Integer.valueOf(value);
}
@Override
public int interpret() {
return this.value;
}
}
5、最后我们还需要一个上下文信息来存储我们的运算结果:
package com.zwx.design.pattern.interpreter;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class ExpressionContext {
private Integer currValue;//记录当前运算结果,空表示暂未运算
private Stack<IExpression> stack = new Stack<>();
public ExpressionContext(String expression) {
this.parse(expression);
}
private void parse(String expression) {
String[] elementArr = expression.split(" ");
for (int i=0;i<elementArr.length;i++){
String element = elementArr[i];
if (element.equals("+")){
IExpression leftExpression = stack.pop();//栈内元素出栈
IExpression rightExpression = new NumberExpression(elementArr[++i]);//取出+号后的下一个元素
IExpression addExpression = new AddExpression(leftExpression,rightExpression);
stack.push(new NumberExpression(addExpression.interpret() + ""));//将计算结果入栈
}else if (element.equals("-")){
IExpression leftExpression = stack.pop();//栈内元素出栈
IExpression rightExpression = new NumberExpression(elementArr[++i]);//取出-号后的下一个元素
IExpression subExpression = new SubExpression(leftExpression,rightExpression);
stack.push(new NumberExpression(subExpression.interpret() + ""));//将计算结果入栈
}else{
stack.push(new NumberExpression(element));//如果是数字则直接入栈
}
}
}
public int calcuate(){
return stack.pop().interpret();//经过前面解析,到这里stack内只会剩下唯一一个数字,即运算结果
}
}
6、最后新建一个测试类来测试一下:
package com.zwx.design.pattern.interpreter;
public class TestInterpreter {
public static void main(String[] args) {
ExpressionContext context = new ExpressionContext("666 + 888 - 777");
System.out.println(context.calcuate());
context = new ExpressionContext("123 - 456 + 11");
System.out.println(context.calcuate());
}
}
运行结果为:
777
-322
从上面示例中,我们可以得出解释器模式主要有4个角色:
这个在源码中的应用大家也应该可以猜测的出来了,比如说JDK中的正则表达式:Pattern类。还有Spring里面的ExpressionParse接口,Spring的这个表达式不知道大家有没有用过,这里面其实也是可以进行加减乘除运算的。如下就是一个简单的应用示例:
所以我们一开始就提到了,像这种解释器模式我们一般在业务开发中用的还是相对较少的,常用的表达式都有人已经帮我们解析好了,直接用就可以了,除非我们从事底层开发自己需要去定义较为复杂的表达式。
解释器模式主要可以运用在如下场景:
优点:
缺点
本文主要介绍了解释器模式的基本使用,并通过一个简单的示例来帮助更好的理解解释器模式,当然这个示例写的比较简单,很多业务逻辑是没有考虑的,但是这些并不是本文的重点,本文的重点是介绍解释器模式的思想。最后我们还介绍了解释器模式模式在相关JDK源码中的体现,希望通过本文,大家可以更深刻的理解解释器模式的设计思想。
请关注我,和孤狼一起学习进步。