首页 > 编程语言 >跟我学Java设计模式第7天:行为型设计模式

跟我学Java设计模式第7天:行为型设计模式

时间:2023-01-28 21:37:39浏览次数:42  
标签:跟我学 解释器 Java int AbstractExpression context 设计模式 public 表达式


Java设计模式文章目录

​​跟我学Java设计模式第一天:设计模式概述和软件设计原则​​

​​跟我学Java设计模式第二天:简单工厂模式、工厂方法模式、抽象工厂模式​​

​​跟我学Java设计模式第三天:代理模式、适配器、装饰者等其中模式结构​​

​​跟我学Java设计模式第4天:结构型模式大全​​

​​跟我学Java设计模式第5天:行为型设计模式汇总​​

​​跟我学Java设计模式第6天:行为型设计模式汇总源码​​


文章目录

  • ​​Java设计模式文章目录​​
  • ​​6,行为型模式​​
  • ​​6.11 解释器模式​​
  • ​​6.11.1 概述​​
  • ​​6.11.2 结构​​
  • ​​6.11.3 案例实现​​
  • ​​6.11.4 优缺点​​
  • ​​6.11.5 使用场景​​

6,行为型模式

6.11 解释器模式

6.11.1 概述

跟我学Java设计模式第7天:行为型设计模式_Express

如上图,设计一个软件用来进行加减计算。我们第一想法就是使用工具类,提供对应的加法和减法的工具方法。

//用于两个整数相加
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),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。

用树形来表示符合文法规则的句子。

跟我学Java设计模式第7天:行为型设计模式_Express_02

6.11.2 结构

解释器模式包含以下主要角色。

  • 抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
  • 终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
  • 非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
  • 环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
  • 客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。

6.11.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;
}

@Override
public int interpret(Context context) {
return value;
}

@Override
public 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;
}

@Override
public int interpret(Context context) {
return left.interpret(context) + right.interpret(context);
}

@Override
public 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;
}

@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}

@Override
public String toString() {
return "(" + left.toString() + " - " + right.toString() + ")";
}
}

//终结符表达式角色 变量表达式
public class Variable extends AbstractExpression {
private String name;

public Variable(String name) {
this.name = name;
}

@Override
public int interpret(Context ctx) {
return ctx.getValue(this);
}

@Override
public String toString() {
return name;
}
}

//环境类
public class Context {
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));
}
}

6.11.4 优缺点

1,优点:

  • 易于改变和扩展文法。
    由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
  • 实现文法较为容易。
    在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂。
  • 增加新的解释表达式较为方便。
    如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合 “开闭原则”。

2,缺点:

  • 对于复杂文法难以维护。
    在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护。
  • 执行效率较低。
    由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

6.11.5 使用场景

  • 当语言的文法较为简单,且执行效率不是关键问题时。
  • 当问题重复出现,且可以用一种简单的语言来进行表达时。
  • 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候。


标签:跟我学,解释器,Java,int,AbstractExpression,context,设计模式,public,表达式
From: https://blog.51cto.com/u_8238263/6025145

相关文章

  • 互联网大厂(字节、华为)Java EE面试题:Servlet/JSP 部分解析+答案,最强八股文
    文章目录​​1.请列举至少6种javaEE技术,并简述其作用。​​​​解析:​​​​参考答案:​​​​2.在web.xml文件中配置Servlet时,主要配置哪些信息?​​​​解析:​​​​参考答......
  • Java零基础05篇:运算符的实际应用
    文章目录​​一、关系运算符(应用)​​​​二、逻辑运算符(应用)​​​​三、三元运算符(理解)​​​​三元运算符案例:​​​​1.需求​​​​2.需求:​​一、关系运算符(应用)关系......
  • Java枚举(Enum)类型原理探求
    Enum枚举类型Enum的全写是Enumeration,这个词的翻译是列举、逐条陈述、细目。在程序语言中,枚举类型是一种特殊的数据类型(常用的数据类型比如字符串、整型),这种数据类型的变量......
  • java面试技巧:Integer和int的那些事⼉
    最近在招聘⾯试的过程中,考察⼀些候选⼈的基础掌握能⼒中发现,还是有⼤多数⼲了有1~3年的开发者在基础这块⼉掌握的不够牢靠,没有去思考过为什么这样做,以及这样做的原因是什么?......
  • java四大引用详解!
    什么是java四大引用? 是JDK1.2版本开始引入,把对象的引用分为4个等级,我们平时学习的就是四种的第一级的强引用,说白了,就Objecto=newObject(),四个引用分别是强引用、软引......
  • Java程序员必看:Solr vip竞价排名
    功能介绍本文将使用solr完成vip等级排名,这里并不是简单的按照vip等级排序。而是在使用solr条件查询(不使用排序)的时候将符合条件并且具有vip等级的数据显示在前面,这个时候......
  • Java:Path及Paths使用
    Java8Windows10-- 主要内容:Windows下测试,组合文件路径、Path转File等。 准备:D盘;D盘下bootweb目录(springboot项目);D盘下test.txt文件;D盘下其它目录及......
  • Java两大工具库:Commons和Guava(2)
    您好,我是湘王,这是我的51CTO博客。值此新春佳节,我给您拜年啦~祝您在新的一年中所求皆所愿,所行皆坦途,展宏“兔”,有钱“兔”,多喜乐,常安宁!开发中有一类应用会出现的比较多,就是文......
  • Java两大工具库:Commons和Guava(2)
    您好,我是湘王,这是我的博客园。值此新春佳节,我给您拜年啦~祝您在新的一年中所求皆所愿,所行皆坦途,展宏“兔”,有钱“兔”,多喜乐,常安宁!   开发中有一类应用会出现的比较......
  • JavaGuide--基础篇
    包装类型的缓存机制了解么?Java基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。Byte,Short,Integer,Long这4种包装类默认创建了数值[-128,127]的相应类......