定义

给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

UML

优点

  1. 将每一个语法规则表示成一个类,方便事先语言。
  2. 因为语法由许多类表示,所以你可以轻易地改变或扩展此语言
  3. 通过在类结构中加入新的方法,可以在解释的同时增加新的行为,例如打印格式的梅花或者进行复制的程序验证。

缺点

  1. 解释器模式会引起类膨胀,每个语法都要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来了非常多的麻烦。
  2. 解释器模式采用递归调用方法,每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,它导致调试非常复杂。想想看,如果要排查一个语法错误,我们是不是要一个一个断点的调试下去,直到最小的语法单元。
  3. 效率问题,解释器模式由于使用了大量的循环和递归,效率是个不容忽视的问题,特别是用于解析复杂、冗长的语法时,效率是难以忍受的。

应用场景

  1. 重复发生的问题可以使用解释器模式。
  2. 一个简单语法需要解释的场景。
  3. 可以处理脚本语言和编程语言,比如正则表达式。

示例

使用解释器模式完成一个两则运算器,要求输入表达式和每个符号的值得到表达式的最终结果。

Java

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Stack; public class Main
{
public static void main(String[] args) throws IOException
{
String expStr = getExpStr();
//赋值
HashMap<String, Integer> var = getValue(expStr);
Calculator cal = new Calculator(expStr);
System.out.println("运算结果为:" + expStr + "=" + cal.run(var));
} /**
* 获得表达式
*/
public static String getExpStr() throws IOException
{
System.out.print("请输入表达式:");
return (new BufferedReader(new InputStreamReader(System.in))).readLine();
} /**
* 获得值映射
*/
public static HashMap<String, Integer> getValue(String exprStr) throws IOException
{
HashMap<String, Integer> map = new HashMap<>();
//解析有几个参数要传递
for (char ch : exprStr.toCharArray())
{
if (ch != '+' && ch != '-')
{
//解决重复参数的问题
if (!map.containsKey(String.valueOf(ch)))
{
System.out.print("请输入" + ch + "的值:");
String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
map.put(String.valueOf(ch), Integer.valueOf(in));
}
}
}
return map;
} /**
* 表达式基类
*/
public static abstract class Expression
{
/**
* 解析公式和数值
* @param var key值是是公式中的参数,value值是具体的数字
* @return 结果
*/
public abstract int interpreter(HashMap<String, Integer> var);
} /**
* 取值表达式
*/
public static class VarExpression extends Expression
{
private String key; public VarExpression(String _key)
{
key = _key;
} @Override
public int interpreter(HashMap<String, Integer> var)
{
return var.get(key);
}
} /**
* 运算表达式,仅关心左右两个值
*/
public static abstract class SymbolExpression extends Expression
{
protected Expression left;
protected Expression right; public SymbolExpression(Expression _left, Expression _right)
{
this.left = _left;
this.right = _right;
}
} /**
* 加法表达式处理
*/
public static class AddExpression extends SymbolExpression
{
public AddExpression(Expression _left, Expression _right)
{
super(_left, _right);
} public int interpreter(HashMap<String, Integer> var)
{
return super.left.interpreter(var) + super.right.interpreter(var);
}
} /**
* 减法表达式处理
*/
public static class SubExpression extends SymbolExpression
{
public SubExpression(Expression _left, Expression _right)
{
super(_left, _right);
} public int interpreter(HashMap<String, Integer> var)
{
return super.left.interpreter(var) - super.right.interpreter(var);
}
} /**
* 运算类
*/
public static class Calculator
{
//定义的表达式
private Expression expression; //构造函数传参,并解析
public Calculator(String expStr)
{
//定义一个堆栈,安排运算的先后顺序
Stack<Expression> stack = new Stack<Expression>();
//表达式拆分为字符数组
char[] charArray = expStr.toCharArray();
//运算
Expression left = null;
Expression right = null;
for (int i = 0; i < charArray.length; i++)
{
switch (charArray[i])
{
case '+': //加法
//加法结果放到堆栈中
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new AddExpression(left, right));
break;
case '-': //减法
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new SubExpression(left, right));
break;
default: //公式中的变量
stack.push(new VarExpression(String.valueOf(charArray[i])));
}
}
//把运算结果抛出来
this.expression = stack.pop();
} //开始运算
public int run(HashMap<String, Integer> var)
{
return this.expression.interpreter(var);
}
}
}

行为类模式(三):解释器(Interpreter)的更多相关文章

  1. python 设计模式之解释器(Interpreter)模式

    #写在前面 关于解释器模式,我在网上转了两三圈,心中有了那么一点概念 ,也不知道自己理解的是对还是错. 其实关于每一种设计模式,我总想找出一个答案,那就是为什么要用这种设计模式, 如果不用会怎么样,会 ...

  2. 行为型模式(十一) 解释器模式(Interpreter)

    一.动机(Motivate) 在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化.在这种情况下,将特定领域的问题表达为某种语法规 ...

  3. 设计模式之行为类模式大PK

                                        行为类模式大PK 行为类模式包括责任链模式.命令模式.解释器模式.迭代器模式.中介者模式.备忘录模式.观察者模式.状态模式.策略 ...

  4. 设计模式之创建类模式大PK

                                        创建类模式大PK 创建类模式包括工厂方法模式.建造者模式.抽象工厂模式.单例模式和原型模式,他们能够提供对象的创建和管理职责.其 ...

  5. 设计模式之行为类模式PK

    行为类模式包括: 责任链模式 命令模式 解释器模式 迭代器模式 中介者模式 备忘录模式 观察者模式 状态模式 策略模式 模板方法模式 访问者模式 行为型模式涉及到算法和对象间职责的分配 行为类模式关注 ...

  6. Singleton单例模式是最简单的设计模式,它的主要作用是保证在程序执行生命周期中,使用了单类模式的类仅仅能有一个实例对象存在。

                                                                                                        ...

  7. Class:向传统类模式转变的构造函数

    前言 JS基于原型的'类',一直被转行前端的码僚们大呼惊奇,但接近传统模式使用class关键字定义的出现,却使得一些前端同行深感遗憾而纷纷留言:"还我独特的JS"."净搞 ...

  8. 创建类模式大PK(总结)

    创建类模式包含工厂方法模式.建造者模式.抽象工厂模式.单例模式和原型模式,它们都可以提供对象的创建和管理职责.当中的单例模式和原型模式很easy理解,单例模式是要保持在内存中仅仅有一个对象,原型模式是 ...

  9. 创建型模式(三) 抽象工厂模式(Abstract Factory)

    一.动机(Motivation) 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作:同时,由于需求的变化,往往存在更多系列对象的创建工作. 如何应对这种变化?如何绕过常规的对象创建方法(ne ...

  10. 设计模式系列之工厂模式三兄弟(Factory Pattern)

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

随机推荐

  1. 解决PHP Fatal error mysql_connect() mysql_query()的问题

    单独安装Apache.PHP.Mysql在进行开发调试的时候经常会遇到各种问题,好多人说比appserv或者xampp集成安装包麻烦,其实不然,单独配置可以更深入的了解每个部件分别是怎么运行的,深入理 ...

  2. hihocoder第218周:AC自动机

    题目链接 问题描述 给定n个单词,给定一个长字符串s,单词总长度和字符串s的长度都不超过1e5.要求把s中所有的出现单词的位置用*替代. 例如: 样例输入 2 abc cd abcxyzabcd 样例 ...

  3. Android开发环境——调试器 DDMS相关内容汇总

       Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT ...

  4. SaltStack 入门到精通第三篇:Salt-Minion配置文件详解

    SaltStack 入门到精通第三篇:Salt-Minion配置文件详解 作者:ArlenJ  发布日期:2014-06-09 17:52:16   ##### 主要配置设置 ##### 配置 默认值 ...

  5. Java正则应用

    private List<String> find(String reg, String str) { Matcher matcher = Pattern.compile(reg).mat ...

  6. ML之回归

    一.概述 一元形式: 多元形式: 最小二乘的目标函数

  7. C# winform DataGridView 常见属性

    C# winform DataGridView 属性说明① 取得或者修改当前单元格的内容 ② 设定单元格只读 ③ 不显示最下面的新行 ④ 判断新增行 ⑤ 行的用户删除操作的自定义 ⑥ 行.列的隐藏和删 ...

  8. C# Log4Net level优先级别

    原文地址:https://blog.csdn.net/pukuimin1226/article/details/51819388?locationNum=2&fps=1 Level定义记录的日 ...

  9. mysql开发常用小结

    1.时间转换 时间戳转时间   FROM_UNIXTIME 比如  FROM_UNIXTIME(1449480551/1000,'%Y-%m-%d %H:%i:%s') 如果是精确到毫秒的时间戳,则必 ...

  10. Windows键盘消息处理

    原文链接: http://blog.sina.com.cn/s/blog_5f8817250100taab.html 本文大部分来自MSDN和网友的博客,我在实践的基础上再作了一些总结. 1,虚拟键( ...