1. 解释器模式概述
解释器模式提供了评估语言的语法或表达式的方式。
这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在SQL解析、符号处理引擎等。
(1) 适用情况
如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
这句话有点晦涩,我自己的理解是,如果一类问题可以分为比较固定的一些语句或者计算的话,那么可以把这些语句或计算封装为一个个类,然后用这些类所表示的子问题组成原问题。通过对各个子问题进行计算,从而得到原问题的结果。
(2) 优点
可拓展性好,灵活。
(3) 缺点
复杂,理解较为困难,不便维护,使用场景较少。
2. 解释器模式实例
这里使用解释器模式,来实现简单的计算器。
(1) 实现上下文类
public class Context {
private Map<Expression, Integer> map = new HashMap<>();
/**
* 增加上下文信息
*/
public void add(Expression expression, int value) {
map.put(expression, value);
}
/**
* 根据上下文信息,将表达式解析为数字
*/
public int convert(Expression expression) {
return map.get(expression);
}
}
(2) 声明表达式接口
public interface Expression {
int interpret(Context context);
}
(3) 实现字符表达式类,表示变量
public class CharacterExpression implements Expression {
String variable;
public CharacterExpression(String variable) {
this.variable = variable;
}
@Override
public int interpret(Context context) {
return context.convert(this);
}
}
(4) 实现数字表达式类,表示常量
public class IntegerExpression implements Expression {
int value;
public IntegerExpression(int value) {
this.value = value;
}
@Override
public int interpret(Context context) {
return value;
}
}
(5) 实现操作符表达式,表示运算
public abstract class OperatorExpression implements Expression {
/**
* 操作符需要两个表达式
*/
Expression expression1;
Expression expression2;
public OperatorExpression(Expression expression1, Expression expression2) {
this.expression1 = expression1;
this.expression2 = expression2;
}
}
(6) 实现加减乘除表达式
public class PlusExpression extends OperatorExpression {
public PlusExpression(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
@Override
public int interpret(Context context) {
int value1 = this.expression1.interpret(context);
int value2 = this.expression2.interpret(context);
return value1 + value2;
}
}
public class MinusExpression extends OperatorExpression {
public MinusExpression(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
@Override
public int interpret(Context context) {
int value1 = this.expression1.interpret(context);
int value2 = this.expression2.interpret(context);
return value1 - value2;
}
}
public class MultiExpression extends OperatorExpression {
public MultiExpression(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
@Override
public int interpret(Context context) {
int value1 = this.expression1.interpret(context);
int value2 = this.expression2.interpret(context);
return value1 * value2;
}
}
public class DivisionExpression extends OperatorExpression {
public DivisionExpression(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
@Override
public int interpret(Context context) {
int value1 = this.expression1.interpret(context);
int value2 = this.expression2.interpret(context);
return value1 / value2;
}
}
(7) 实现幂运算表达式
public abstract class PowExpression implements Expression {
/**
* 幂运算只需要一个表达式
*/
Expression expression;
public PowExpression(Expression expression) {
this.expression = expression;
}
}
(8) 实现平方和立方表达式
public class Pow2Expression extends PowExpression {
public Pow2Expression(Expression expression) {
super(expression);
}
/**
* 计算平方
*/
@Override
public int interpret(Context context) {
int value = this.expression.interpret(context);
return value * value;
}
}
public class Pow3Expression extends PowExpression {
public Pow3Expression(Expression expression) {
super(expression);
}
/**
* 计算立方
*/
@Override
public int interpret(Context context) {
int value = this.expression.interpret(context);
return value * value * value;
}
}
(9) 进行计算
public class InterpreterDemo {
public static void main(String[] args) {
// 题目:计算(x^3 + (y^2 - z * 2)) / 2等于多少
// 其中x = 3, y = 3, z = 1
// 构造x,y,z变量和数字2
CharacterExpression x = new CharacterExpression("x");
CharacterExpression y = new CharacterExpression("y");
CharacterExpression z = new CharacterExpression("z");
IntegerExpression num2 = new IntegerExpression(2);
// 构造y^2
Pow2Expression pow2Expression = new Pow2Expression(y);
// 构造z * 2
MultiExpression multiExpression = new MultiExpression(z, num2);
// 构造(y^2 - z * 2)
MinusExpression minusExpression = new MinusExpression(pow2Expression, multiExpression);
// 构造x^3
Pow3Expression pow3Expression = new Pow3Expression(x);
// 构造(x^3 + (y^2 - z * 2))
PlusExpression plusExpression = new PlusExpression(pow3Expression, minusExpression);
// 构造(x^3 + (y^2 - z * 2)) / 2
DivisionExpression divisionExpression = new DivisionExpression(plusExpression, num2);
// 给上下文赋值
Context context = new Context();
// x = 3
context.add(x, 3);
// y = 3
context.add(y, 3);
// z = 1
context.add(z, 1);
// 计算结果
System.out.println(divisionExpression.interpret(context));
}
}
运算结果:
3. 一些思考
解释器模式算是最复杂的一类设计模式了。
Express接口中有一个方法interpret,入参Context为上下文,表示根据上下文进行解释。
每个Expression的实现类都需要实现该方法,来表明如何进行根据上下文进行解释。
CharacterExpression表示变量,比如题目中的x、y、z;
IntegerExpression表示常量,比如题目中的2。
它们都实现了Expression接口。
OperatorExpression和PowExpression分别表示操作符运算和幂运算。
它们也都实现了Expression接口。
Context表示上下文,也就是题目中变量所对应的值。
其中有两个方法,add方法用来增加上下文信息,convert方法用来将变量解析为数字常量。
参考引用
解释器模式:www.runoob.com/design-patt…
解释器模式:blog.csdn.net/niunai112/a…