我有一个 Java 应用程序,我需要在其中将一个简单的算术表达式表示为一棵树。我将支持的操作包括一元(!、一元否定等)、二元(+、-、*、/)甚至三元(自定义函数)操作。因此,我选择了 DefaultMutableTreeNode
作为表示我的数学树的结构,因为这些树可以有 0+ 个子节点。
例如,表达式:3 + 4 * someFunc(2, 6, 9)
将表示为以下树:
*
/ \
/ \
/ \
+ someFunc
/ \ /|\
/ \ / | \
3 4 2 6 9
这是因为运算符优先级(乘法胜过加法,someFunc
方法必须先解析为一个值,然后它才能作为根乘法的参数)。
无论如何,我需要一种方法来轻松地以编程方式构建这些树,并且想使用 Java DSL(Fluent Builder
模式)来完成此任务。
对于节点:
public abstract class MathNode {
}
public abstract class OperatorNode extends MathNode {
}
public class Addition extends OperatorNode {
// Same for Multiplication, SomeFunc, and every other supported operator.
}
public class Number extends MathNode {
// 3, 4, 2, 6, 9, etc.
}
然后,我可能会像这样拥有一个流畅的构建器/DSL:
// Uses DefaultMutableTreeNode for internal structure.
MathTreeBuilder treeBuilder = new MathTreeBuilder();
treeBuilder.multiply()
.add(3,4)
.someFunc(2,6,9);
MathTree tree = treeBuilder.build();
然而,我在这里很难透过“树木”看到“森林”。我是否需要构建器,或者我是否可以通过将 DSL 与 MathTree
分开来完成同样的工作?本身? DSL 会是什么样子——我是在走上正轨还是我误解了流式构建器模式的使用?而且,最重要的是,在每种不同的 DSL 方法( add()
、 multiply()
、 someFunc()
等)中,我实际上如何着手修改 DefaultMutableTreeNode
准确地表示树?p>
最佳答案
我认为您应该按照 XML 构建器的工作方式来处理:
- 是的,使用流畅的 API;
- 无需严格遵循构建器模式:您不必通过“导出”到不可变对象(immutable对象)来完成构建;
- 在您的构建器内部,维护树和您在其中的当前位置:当前接收子节点的节点;
- 有一个明确的
end()
方法,它使当前节点的父节点成为新的当前节点。
然后你可以构建你的 3 + 4 * someFunc(2, 6, 9)
如下:
new MathBuilder()
.add()
.const(3)
.multiply()
.const(4)
.someFunc()
.const(2)
.const(6)
.const(9)
.end()
.get();
所有尾随的 end()
调用都可以省略。我留了一个作为例子。
关于java - Java 中的 Fluent Builder/DSL 示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22461333/