解释器模式
他是一种特殊的设计模式,他建立一个解释器,对于特定的计算机程序设计语言,用来
解释预先定义的文法,简单的讲,解释器模式interpreter是一种简单的语法解释器框架
应用场景:当一个介绍语言需要执行并且可将该语言中的句子表示为一个抽象语法树,可以使用
解释器模式,而存在以下情况时候效果更好
1 该语法对于复杂的文法,文法的类层次变得庞大而无法管理,此时语法分析程序生成器这个月的工具
是更好的选择,他们无需构建抽象的语法树即可以解释表达式,这样节省空间而且还可以节省时间
2 效率不是一个关键问题,最搞笑的解释器通常不是通过直接解释语法分析树实现。
而是首先转换成另一种形式,例如正则表达式通常转化为状态机,但即使这种情况下转化器仍可以用解释器模式
实现,该模式仍有用
一般主要应用在OOP开发中的编译器的开发中,所以适用面比较窄。
实例代码一:
/**
* 一般主要应用在OOP开发中的编译器的开发中,所以适用面比较窄
* Context类是一个上下文环境类,Plus和Minus分别是用来计算的实现,代码如下:。
*/
public interface Expression {
public int interpret(Context context);
}
*************************************************************
public class Context {
private int num1;
private int num2;
public Context(int num1, int num2) {
this.num1 = num1;
this.num2 = num2;
}
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
}
*************************************************************
public class Minus implements Expression {
@Override
public int interpret(Context context) {
return context.getNum1()-context.getNum2();
}
}
*************************************************************
public class Plus implements Expression {
@Override
public int interpret(Context context) {
return context.getNum1()+context.getNum2();
}
}
*************************************************************
public class MainClass {
public static void main(String[] args) {
// 计算9+2-8的值
Context contextPlus = new Context(9, 2);
Expression ePlus = new Plus();
Expression eMinus = new Minus();
int temp = ePlus.interpret(contextPlus);
int result = eMinus.interpret(new Context(temp, 8));
System.out.println(result);
}
}
*************************************************************
测试结果:
3
*************************************************************
实例代码二:
/**
* 上下环境,用来保存文法
*/
public class Context {
private String input;
private int output;
public int getOutput() {
return output;
}
public void setOutput(int output) {
this.output = output;
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
}
******************************************************
public abstract class Expression {
public abstract void interpret(Context context);
}
******************************************************
/**
* 自动递减
*/
public class MinusExpression extends Expression{
@Override
public void interpret(Context context) {
System.out.println("自动递减");
//获取上下文参数
String input = context.getInput();
int i = Integer.parseInt(input);
//自动递减
--i;
context.setInput(String.valueOf(i));
context.setOutput(i);
}
}
******************************************************
/**
* 自动递增
*/
public class PlusExpression extends Expression {
@Override
public void interpret(Context context) {
System.out.println("自动递增");
//获取上下文参数
String input = context.getInput();
int i = Integer.parseInt(input);
//自动递增
i++;
context.setInput(String.valueOf(i));
context.setOutput(i);
}
}
******************************************************
public class MainClass {
public static void main(String[] args) {
Context context = new Context();
context.setInput("10");
Expression plus = new PlusExpression();
plus.interpret(context);
System.out.println(context.getOutput());
Expression minus = new MinusExpression();
minus.interpret(context);
System.out.println(context.getOutput());
}
}
******************************************************
测试结果:
自动递增
11
自动递减
10
******************************************************
******************************************************
三、事例
拆解表达式,将非终结表达式拆解为不可拆分的终结表达式,结构与组合模式类型
先定义一个表达式,环境上下文Context这里不加,有需要的可以在接口参数找那个设置Context
void interpret(Context context);
public interface Expression {
// 解释,翻译
void interpret();
}
移动鼠标
public class Move implements Expression{
private int x;
private int y;
public Move(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public void interpret() {
System.out.println("移动鼠标:【" + x + "," + y + "】");;
}
}
按下左键
public class LeftDown implements Expression{
@Override
public void interpret() {
System.out.println("按下鼠标:左键");
}
}
松开左键
public class LeftUp implements Expression{
@Override
public void interpret() {
System.out.println("松开鼠标:左键");
}
}
单击左键:包含按下左键,松开左键
public class LeftClick implements Expression {
private Expression leftDown;
private Expression LeftUp;
public LeftClick(Expression leftDown, Expression leftUp) {
this.leftDown = leftDown;
LeftUp = leftUp;
}
@Override
public void interpret() {
//单击:左键按下->左键松开
leftDown.interpret();
LeftUp.interpret();
}
}
系统延时
public class Delay implements Expression {
private int second;
public Delay(int second) {
this.second = second;
}
@Override
public void interpret() {
System.out.println("系统延迟:" + second + "s");
try {
TimeUnit.SECONDS.sleep(second);
} catch (InterruptedException e) {
System.out.println("异常"+e.getMessage());
}
}
}
按下右键
public class RightDown implements Expression{
@Override
public void interpret() {
System.out.println("按下鼠标:右键");
}
}
指令集
public class Sequence implements Expression{
// 指令集
private List<Expression> expressions;
public Sequence(List<Expression> expressions) {
this.expressions = expressions;
}
@Override
public void interpret() {
expressions.forEach(expression -> expression.interpret());
}
}
循环结构
public class Repetition implements Expression {
private int loopCount;// 循环次数
private Expression expression; // 循环表达式
public Repetition(int loopCount, Expression expression) {
this.loopCount = loopCount;
this.expression = expression;
}
@Override
public void interpret() {
while (loopCount > 0) {
expression.interpret();
loopCount--;
}
}
}
打印输出
public class MainClient {
public static void main(String[] args) {
// interpreter 解释器,翻译器的意思
//BEGIN // 脚本开始
//MOVE 500,600; // 鼠标移动到坐标(500, 600)
// BEGIN LOOP 5 // 开始循环5次
// LEFT_CLICK; // 循环体内单击左键
// DELAY 1; // 每次延时1秒
// END; // 循环体结束
//RIGHT_DOWN; // 按下右键
//DELAY 7200; // 延时2小时
//END; // 脚本结束
Expression sequence = new Sequence(Arrays.asList(new Move(500, 600)
, new Repetition(5, new Sequence(Arrays.asList(
new LeftClick(new LeftDown(), new LeftUp())
, new Delay(1))))
, new RightDown()
, new Delay(7200)));
sequence.interpret();
//移动鼠标:【500,600】
//按下鼠标:左键
//松开鼠标:左键
//系统延迟:1s
//按下鼠标:左键
//松开鼠标:左键
//系统延迟:1s
//按下鼠标:左键
//松开鼠标:左键
//系统延迟:1s
//按下鼠标:左键
//松开鼠标:左键
//系统延迟:1s
//按下鼠标:左键
//松开鼠标:左键
//系统延迟:1s
//按下鼠标:右键
//系统延迟:7200s
}
}