解释器模式
解释器模式(Interpreter Pattern)是一种按照规定语法对表达式进行解析的方案,在项目中使用较少。
1解释器模式的定义
解释器模式的英文原话:
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
意思是:给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
解释器有5个角色:
- 抽象表达式(Abstract Expression)角色:该角色声明一个所有的具体表达式角色都需要实现的抽象接口,该接口主要是一个解释操作interpret()方法。
- 终结符表达式(Terminal Expression)角色:该角色实现了抽象表达式角色所要求的接口,文法中的每一个终结符都有一个具体终结表达式与之对应。
- 非终结符表达式(Noneterminal Expression)角色:该角色是一个具体角色,文法中的每一条规则都对应一个非终结符表达式类。
- 环境(Context)角色:该角色提供解释器之外的一些全局信息。
- 客户端(Client)角色: 该角色创建一个抽象语法树,调用解释操作。
2解释器模式的应用
a.解释器模式的优缺点
解释模式的优点
- 简单的语法分析工具
- 扩展性,修改语法规则只要修改相应的非终结符表达式即可,若扩展语法,则只要增加非终结符类即可。
解释器模式的缺点
- 解释器模式会引起类膨胀。每个语法都要产生一个非终结符表达式,语法比较复杂时就可能产生大量的类文件,不易维护。
- 采用递归调用方法。每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,不易调试且影响效率。
b.解释器模式的使用场景
- 重复发生的问题可以使用解释器模式。例如,多个应用服务器,每天产生大量的日志,需要对日志文件进行分析处理,由于各个服务器的日志格式是不同的,但是数据要素是相同的,按照解释器的说法就是终结符表达式都是相同的,非终结符表达式就需要定制。
- 一个简单语法需要解释的场景。
3解释器模式的实例
使用解释器模式完成四则算数运算表达式的计算。
创建算术表达式,抽象解释器角色
ArithmeticExpression.java
package com.eric.行为型模式_Part2.解释器模式.例1;
import com.sun.org.apache.xpath.internal.operations.VariableSafeAbsRef;
/**
* @author Eric
* @ProjectName my_design_23
* @description 算术表达式,抽象解释器角色
* @CreateTime 2020-12-15 18:08:12
*/
public interface ArithmeticExpression {
int interpret(Variables variables);
}
创建变量类
Variable.java
package com.eric.行为型模式_Part2.解释器模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 变量
* @CreateTime 2020-12-15 18:09:39
*/
public class Variable implements ArithmeticExpression{
@Override
public int interpret(Variables variables) {
return variables.get(this);
}
}
存储变量值的类
Variables.java
package com.eric.行为型模式_Part2.解释器模式.例1;
import java.util.HashMap;
/**
* @author Eric
* @ProjectName my_design_23
* @description 使用map存储各个变量的值
* @CreateTime 2020-12-15 18:10:42
*/
public class Variables {
HashMap<Variable,Integer> v = new HashMap<Variable,Integer>();
public void put(Variable variable , int value)
{
v.put(variable,value);
}
public int get(Variable variable)
{
return v.get(variable);
}
}
创建抽象表达式的4种解析器
Plus.java
package com.eric.行为型模式_Part2.解释器模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 加法
* @CreateTime 2020-12-15 18:13:28
*/
public class Plus implements ArithmeticExpression {
ArithmeticExpression left;
ArithmeticExpression right;
public Plus(ArithmeticExpression left,ArithmeticExpression right)
{
this.left = left;
this.right = right;
}
@Override
public int interpret(Variables variables) {
return left.interpret(variables) + right.interpret(variables);
}
}
Substract.java
package com.eric.行为型模式_Part2.解释器模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 减法
* @CreateTime 2020-12-15 18:16:45
*/
public class Subtract implements ArithmeticExpression{
ArithmeticExpression left;
ArithmeticExpression right;
public Subtract(ArithmeticExpression left,ArithmeticExpression right)
{
this.left = left;
this.right = right;
}
@Override
public int interpret(Variables variables) {
return left.interpret(variables) - right.interpret(variables);
}
}
Multiply.java
package com.eric.行为型模式_Part2.解释器模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 乘法
* @CreateTime 2020-12-15 18:18:35
*/
public class Multiply implements ArithmeticExpression {
ArithmeticExpression left;
ArithmeticExpression right;
public Multiply(ArithmeticExpression left,ArithmeticExpression right)
{
this.left = left;
this.right = right;
}
@Override
public int interpret(Variables variables) {
return left.interpret(variables) * right.interpret(variables);
}
}
Division.java
package com.eric.行为型模式_Part2.解释器模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 除法
* @CreateTime 2020-12-15 18:19:30
*/
public class Division implements ArithmeticExpression {
ArithmeticExpression left;
ArithmeticExpression right;
public Division(ArithmeticExpression left,ArithmeticExpression right)
{
this.left = left;
this.right = right;
}
@Override
public int interpret(Variables variables) {
return left.interpret(variables) / right.interpret(variables);
}
}
客户端类
ClientDemo.java
package com.eric.行为型模式_Part2.解释器模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 客户端
* @CreateTime 2020-12-15 18:20:20
*/
public class ClientDemo {
public static void main(String[] args) {
Variables v = new Variables();
Variable x = new Variable();
Variable y = new Variable();
Variable z = new Variable();
v.put(x,10);
v.put(y,20);
v.put(z,30);
//计算 x*(y+z/x) - x
// 10*(20+30/10) - 10 = 220
ArithmeticExpression e = new Subtract(
new Multiply(x,
new Plus(y,
new Division(z,x))),x);
System.out.println(e.interpret(v));
}
}
测试结果
![](https://img2020.cnblogs.com/blog/1989411/202105/1989411-20210510143633085-2062472714.png)