目录
3)非终结符表达式(Non-Terminal Expression)
1.解释器模式概念
它允许为语言定义一个语法,并且可以创建一个解析器来解释该语言中的句子。这种模式主要用于解决当有一个语言需要解释执行,并且你希望将该语言中的句子表示为一个抽象语法树时。
2.解释器模式的组成
1)抽象表达式(Abstract Expression)
定义了解释器的接口,包含了解释方法 interpret。
2)终结符表达式(Terminal Expression)
实现与文法中的终结符相关的操作。
3)非终结符表达式(Non-Terminal Expression)
包含对其他表达式的引用,并在解释过程中根据文法规则组合这些表达式的结果。
4)上下文(Context)
包含解释器之外的一些全局信息,可能被各个解释器使用。
3.举个栗子
以加减乘除为例
如下图
左侧部分
左侧部分展示了解释器模式的类结构:
- Calculation(运算抽象接口):这是所有表达式的基类,定义了求值的方法。
- Number(数字终结表达式):表示数字的类,继承自Calculation,表示一个具体的数字。
- Symbols(符号非中介表达式):表示运算符的类,继承自Calculation,包括加法(add)、减法(sub)、除法(div)和乘法(mul)。
右侧部分
右侧部分展示了如何使用这些类来构建一个数学表达式树:
- 表达式:
((1 + 2) + 3) - 4
- 表达式树:
- 根节点是
sub
(减法),表示整个表达式的结构。 sub
的左子节点是add
(加法),表示(1 + 2) + 3
。add
的左子节点是1
,表示数字1。add
的右子节点是add
,表示2 + 3
。add
的左子节点是2
,表示数字2。add
的右子节点是3
,表示数字3。sub
的右子节点是4
,表示数字4。
- 根节点是
通过这种方式,可以将复杂的数学表达式分解为一个树结构,然后通过递归地求值每个节点来计算整个表达式的结果。
4.代码实现
1)抽象表达式
Calculation
定义了一个名为 Calculation 的接口,其中包含一个名为 calculate 的方法。这个接口可以用于定义各种计算逻辑。
package org.xiji.interpreter;
/**
* 定义计算接口
*/
public interface Calculation {
/**
* 计算结果
*/
double calculate();
}
2)终结表达式
Number
· Number 类通过实现 Calculation 接口,提供了一个简单的数字存储和计算功能。
· 构造方法和 getter/setter 方法使得 Number 对象可以方便地创建和修改。
· calculate 方法返回存储的数字值,符合 Calculation 接口的要求。
package org.xiji.interpreter;
/**
* 实现数字类
*/
public class Number implements Calculation{
private double number;
public Number() {
}
public Number(double number) {
this.number = number;
}
public double getNumber() {
return number;
}
public void setNumber(double number) {
this.number = number;
}
@Override
public double calculate() {
return number;
}
}
3)非终结表达式
Symbols
· Symbols 抽象类提供了一个通用的框架,用于实现各种二元运算符。
· 子类通过继承 Symbols 并实现 calculate 方法,可以具体实现不同的运算逻辑。
· 这种设计使得代码更加模块化和可扩展,便于管理和维护。
package org.xiji.interpreter;
/**
* 实现符号抽象类
*/
public abstract class Symbols implements Calculation{
/**
* 左边 右边
*
*/
protected Calculation left;
protected Calculation right;
public Symbols( Calculation left, Calculation right) {
this.left = left;
this.right = right;
}
@Override
public abstract double calculate() ;
}
add
· Add 类继承自 Symbols 抽象类,并实现了加法运算。
· 构造方法通过调用父类的构造方法来初始化左右操作数。
· calculate 方法实现了具体的加法逻辑,返回两个操作数的和。
package org.xiji.interpreter;
public class Add extends Symbols{
public Add(Calculation left, Calculation right) {
super(left, right);
}
@Override
public double calculate() {
//减法
return super.left.calculate() + super.right.calculate();
}
}
sub
· Sub 类继承自 Symbols 抽象类,并实现了减法运算。
· 构造方法通过调用父类的构造方法来初始化左右操作数。
· calculate 方法实现了具体的减法逻辑,返回两个操作数的差。
package org.xiji.interpreter;
public class Sub extends Symbols{
public Sub(Calculation left, Calculation right) {
super(left, right);
}
@Override
public double calculate() {
//减法
return super.left.calculate() - super.right.calculate();
}
}
div
· Div 类继承自 Symbols 抽象类,并实现了除法运算。
· 构造方法通过调用父类的构造方法来初始化左右操作数。
· calculate 方法实现了具体的除法逻辑,返回两个操作数的商,并检查除数是否为零,避免除以零的情况。
package org.xiji.interpreter;
public class Div extends Symbols{
public Div(Calculation left, Calculation right) {
super(left, right);
}
@Override
public double calculate() {
//除法
return super.left.calculate() / super.right.calculate();
}
}
mul
· Mul 类继承自 Symbols 抽象类,并实现了乘法运算。
· 构造方法通过调用父类的构造方法来初始化左右操作数。
· calculate 方法实现了具体的乘法逻辑,返回两个操作数的乘积。
package org.xiji.interpreter;
public class Mul extends Symbols{
public Mul(Calculation left, Calculation right) {
super(left, right);
}
@Override
public double calculate() {
//乘法
return super.left.calculate() * super.right.calculate();
}
}
4)测试类
· InterpreterMain 类通过组合不同的运算符类来计算复杂的表达式。
· 每个运算符类(如 Add, Sub, Mul, Div)都实现了具体的运算逻辑。
· 通过递归组合这些运算符类,可以构建任意复杂的表达式并计算其结果。
package org.xiji.interpreter;
/**
* 解释器模式测试
*/
public class InterpreterMain {
public static void main(String[] args) {
//以 1+2+3-4为例
Sub sub = new Sub(
new Add(
new Add(
new Number(1), new Number(2)
), new Number(3)
), new Number(4)
);
double calculate = sub.calculate();
System.out.println("1+2+3-4");
System.out.println("( ( ( 1+2 ) + 3) + 4) ");
System.out.println(calculate);
//构建 2*3+6/5+3
/**
* ((2*3) +(6/5) +3 )
*/
Add add = new Add(
new Add(
new Mul(
new Number(2), new Number(3)
),
new Div(
new Number(6), new Number(5)
)
),
new Number(3)
);
System.out.println("2*3+6/5+3");
System.out.println("((2*3) +(6/5) +3 )");
System.out.println(add.calculate());
}
}
5.运行结果
附录:
1)23种设计模式讲解地址
23种设计模式讲解地址
专题地址:https://blog.csdn.net/2301_76862031/category_12779841.html
设计模式之访问者模式地址: https://blog.csdn.net/2301_76862031/article/details/141716629
设计模式之简单工厂模式地址: https://blog.csdn.net/2301_76862031/article/details/141641161
设计模式之策略模式工厂地址:https://blog.csdn.net/2301_76862031/article/details/141647304
设计模式之备忘录模式地址: https://blog.csdn.net/2301_76862031/article/details/141678153
设计模式之代理模式: https://blog.csdn.net/2301_76862031/article/details/141681834
设计模式之单例模式: https://blog.csdn.net/2301_76862031/article/details/141684340
设计模式之迭代器模式: https://blog.csdn.net/2301_76862031/article/details/141690379
设计模式之观察者模式:https://blog.csdn.net/2301_76862031/article/details/141723684
设计模式之命令模式: https://blog.csdn.net/2301_76862031/article/details/141728371
设计模式之模板方法模式: https://blog.csdn.net/2301_76862031/article/details/141729898
设计模式之桥接模式: https://blog.csdn.net/2301_76862031/article/details/141748997
设计模式之适配器模式: https://blog.csdn.net/2301_76862031/article/details/141752130
设计模式之外观模式: https://blog.csdn.net/2301_76862031/article/details/141753019
设计模式之享元模式: https://blog.csdn.net/2301_76862031/article/details/141755905
设计模式之原型模式: https://blog.csdn.net/2301_76862031/article/details/141759296
设计模式之责任链模式: https://blog.csdn.net/2301_76862031/article/details/141760704
设计模式之中介模式: https://blog.csdn.net/2301_76862031/article/details/141777728
设计模式之装饰者模式: https://blog.csdn.net/2301_76862031/article/details/141784167
设计模式之状态模式: https://blog.csdn.net/2301_76862031/article/details/141786766
设计模式之组合模式: https://blog.csdn.net/2301_76862031/article/details/141787708
设计模式之工厂方法模式: https://blog.csdn.net/2301_76862031/article/details/141826862
设计模式之解释器模式: https://blog.csdn.net/2301_76862031/article/details/141859953