最后一个行为型模式:解释器
学习设计模式,让你提升百倍
专栏 | 重点文章 |
---|---|
设计模式 | 设计模式基础前奏(上) |
设计模式 | 设计模式基础前奏(下) |
设计模式 | 创建者模式之单例模式 |
设计模式 | 创建者模式之工厂模式 |
设计模式 | 创建者模式之原型模式 |
设计模式 | 创建者模式之建造者模式 |
设计模式 | 结构型模式之代理模式 |
设计模式 | 结构型模式之适配器模式 |
设计模式 | 行为型模式之模板方法模式 |
设计模式 | 行为型模式之策略模式 |
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。
行为型模式分为:
- 模板方法模式重要
- 策略模式重要
- 命令模式
- 职责链模式
- 状态模式
- 观察者模式
- 中介者模式
- 迭代器模式
- 访问者模式
- 备忘录模式
- 解释器模式
以上 11 种行为型模式,除了模板方法模式和解释器模式是类行为型模式,其他的全部属于对象行为型模式。
解释器模式
- 1 概述
- 2 结构
- 3 案例实现
- 4 优缺点
- 5 使用场景
1 概述
如上图,设计一个软件用来进行加减计算。我们第一想法就是使用工具类,提供对应的加法和减法的工具方法。
//用于两个整数相加
public static int add(int a,int b){return a + b;
}//用于两个整数相加
public static int add(int a,int b,int c){return a + b + c;
}//用于n个整数相加
public static int add(Integer ... arr) {int sum = 0;for (Integer i : arr) {sum += i;}return sum;
}
上面的形式比较单一、有限,如果形式变化非常多,这就不符合要求,因为加法和减法运算,两个运算符与数值可以有无限种组合方式。比如 1+2+3+4+5、1+2+3-4等等。
显然,现在需要一种翻译识别机器,能够解析由数字以及 + - 符号构成的合法的运算序列。如果把运算符和数字都看作节点的话,能够逐个节点的进行读取解析运算,这就是解释器模式的思维。
定义:
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
在解释器模式中,我们需要将待解决的问题,提取出规则,抽象为一种“语言”。比如加减法运算,规则为:由数值和±符号组成的合法序列,“1+3-2” 就是这种语言的句子。
解释器就是要解析出来语句的含义。但是如何描述规则呢?
文法(语法)规则:
文法是用于描述语言的语法结构的形式规则。
expression ::= value | plus | minus
plus ::= expression ‘+’ expression
minus ::= expression ‘-’ expression
value ::= integer
注意: 这里的符号“::=”表示“定义为”的意思,竖线 | 表示或,左右的其中一个,引号内为字符本身,引号外为语法。
上面规则描述为 :
表达式可以是一个值,也可以是plus或者minus运算,而plus和minus又是由表达式结合运算符构成,值的类型为整型数。
抽象语法树:
在计算机科学中,抽象语法树(AbstractSyntaxTree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。
用树形来表示符合文法规则的句子。
2 结构
解释器模式包含以下主要角色。
抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。
3 案例实现
【例】设计实现加减法的软件
代码如下:
//抽象表达式角色AbstractExpression
public abstract class AbstractExpression {public abstract int interpret(Context context);
}//终结符表达式角色
public class Value extends AbstractExpression {private int value;public Value(int value) {this.value = value;}@Overridepublic int interpret(Context context) {return value;}@Overridepublic String toString() {return new Integer(value).toString();}
}//非终结符表达式角色 加法表达式
public class Plus extends AbstractExpression {private AbstractExpression left;private AbstractExpression right;public Plus(AbstractExpression left, AbstractExpression right) {this.left = left;this.right = right;}@Overridepublic int interpret(Context context) {return left.interpret(context) + right.interpret(context);}@Overridepublic String toString() {return "(" + left.toString() + " + " + right.toString() + ")";}
}//非终结符表达式角色 减法表达式
public class Minus extends AbstractExpression {private AbstractExpression left;private AbstractExpression right;public Minus(AbstractExpression left, AbstractExpression right) {this.left = left;this.right = right;}@Overridepublic int interpret(Context context) {return left.interpret(context) - right.interpret(context);}@Overridepublic String toString() {return "(" + left.toString() + " - " + right.toString() + ")";}
}//终结符表达式角色 变量表达式(封装变量的类)
public class Variable extends AbstractExpression {private String name;public Variable(String name) {this.name = name;}public int interpret(Context ctx) {//直接返回变量的值return ctx.getValue(this);}@Overridepublic String toString() {return name;}
}//环境角色类
public class Context {//定义一个map集合,用来存储变量及对应的值private Map<Variable, Integer> map = new HashMap<Variable, Integer>();//添加变量的功能public void assign(Variable var, Integer value) {map.put(var, value);}public int getValue(Variable var) {Integer value = map.get(var);return value;}
}//测试类
public class Client {public static void main(String[] args) {//创建环境对象Context context = new Context();//创建多个变量对象Variable a = new Variable("a");Variable b = new Variable("b");Variable c = new Variable("c");Variable d = new Variable("d");Variable e = new Variable("e");//Value v = new Value(1);//将变量存储到环境对象中context.assign(a, 1);context.assign(b, 2);context.assign(c, 3);context.assign(d, 4);context.assign(e, 5);//获取抽象语法树AbstractExpression expression = new Minus(new Plus(new Plus(new Plus(a, b), c), d), e);//解释(计算)System.out.println(expression + "= " + expression.interpret(context));}
}
4 优缺点
1,优点:
易于改变和扩展文法。
由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
实现文法较为容易。
在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂。
增加新的解释表达式较为方便。
如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合 “开闭原则”。
2,缺点:
对于复杂文法难以维护。
在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护。
执行效率较低。
由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
5 使用场景
当语言的文法较为简单,且执行效率不是关键问题时。
当问题重复出现,且可以用一种简单的语言来进行表达时。
当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候。
最后一个行为型模式:解释器相关推荐
- 《设计模式详解》行为型模式 - 解释器模式
解释器模式 6.11 解释器模式 6.11.1 概述 6.11.2 结构 6.11.3 案例实现 6.11.4 优缺点 6.11.5 使用场景 完整的笔记目录:<设计模式详解>笔记目录,欢 ...
- 设计模式 — 行为型模式 — 解释器模式
目录 文章目录 目录 解释器模式 应用场景 代码示例 解释器模式 解释器模式,开发者自定义一种 "有内涵" 的语言(或者叫字符串),并设定相关的解释规则,输入该字符串后可以输出公认 ...
- 行为型模式-解释器模式(Interpreter)
定义 解释器模式,就是定义语言的文法,并建立一个解释器来解释该语言中的句子,通过构建解释器,解决某一频繁发生的特定类型问题实例. 解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语 ...
- Java设计模式之行为型:解释器模式
一.什么是解释器模式: 解释器模式,就是定义语言的文法,并建立一个解释器来解释该语言中的句子,通过构建解释器,解决某一频繁发生的特定类型问题实例. 这里我们将语言理解成使用规定格式和语 ...
- Interpreter(解释器)--类行为型模式
Interpreter(解释器)–类行为型模式 一.意图 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 二.动机 1.在软件构建过程中,如果某一特定 ...
- 行为型模式:解释器模式
原文首发: 行为型模式:解释器模式 十一大行为型模式之十:解释器模式. 简介 姓名 :解释器模式 英文名 :Interpreter Pattern 价值观 :不懂解释到你懂 个人介绍 : Given ...
- 行为型模式(7)——解释器模式
定义 给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子.也就是说,用编译语言的方式来分析应用中的实例.这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文. ...
- Java实现二十三种设计模式(五)—— 十一种行为型模式 (中)——解释器模式、迭代器模式、中介者模式、备忘录模式
Java实现二十三种设计模式(五)-- 十一种行为型模式 (中)--解释器模式.迭代器模式.中介者模式.备忘录模式 一.解释器模式 我国 IT 界历来有一个汉语编程梦,虽然各方对于汉语编程争论不休,甚 ...
- 三、行为型模式【访问者模式、备忘录模式、命令模式、解释器模式、中介模式】
访问者模式 允许一个或者多个操作应用到一组对象上,解耦操作和对象本身,保持类职责单一.满足开闭原则以及应对代码的复杂性. 多态是一种动态绑定,可以在运行时获取对象的实际类型,来运行实际类型对应的方法. ...
最新文章
- Linux系统挂载ntfs分区
- maven_SonarQube中的Maven项目的单元和集成测试报告
- Windows路由表配置:双网卡同时上内外网
- java 普通项目转web项目
- (学)咱们换一种说法!
- 网络拓扑图画图工具_写了100多篇原创文章,我常用的在线工具网站推荐给大家!...
- 反转链表python
- fastclick.js解决移动端(ipad)点击事件反应慢问题
- glibc2.31下的新double free手法/字节跳动pwn题gun题解
- 计算机组成与结构1800题,最新版数据结构1800题含完整答案详解
- MQTT如何快速助你产品化
- android 8.0手机无法更新版本,微信8.0安卓机怎么安装更新 安卓微信更新不了8.0解决办法一览...
- 怎么使用股票委托下单接口?
- 手游推广,经营一家游戏公司需要多少人?
- AR家居,随时随地在家“玩装修”!
- Imagemagick转换图片成ico
- 《后端从入门到熟悉-序言》
- 【JavaSE】算术运算符、关系运算符、逻辑运算符、赋值运算符与三元运算符
- Python编程之numpy库函数in1d的使用
- 一个实现粒子爆炸效果的控件