引子
公司里一项目使用work flow, 使用的是JBoss jBPM.存储为xml格式,需求如下
1) xml文档和business model: node class 实例之间的相互转换
2) 检查整个tree的高度和宽度,避免用户创建太深或者太宽的work flow
3) 检查node的名称,不容许有重复的命名
xml 样例
business model
Db Design
DB存储时
- 每个WorkFlow存成一条记录
- WorkFlow中的每个节点存成一条记录
- 节点之间的关系通过xml保存在WorkFlow table中
WorkFlow
| id | name | xmlContent|
WorkFlowNode
| id | workFlowId | name |
递归(recursive)
最大高度 (后序,先得到child的高度,然后是当前节点的高度: maxChildHeight + 1)
最大宽度 (前序后序皆可)
使用数组作为int类型的holder,因为java里面没有指针,而且java的Integer为Immutable类型
非递归(non-recursive) 泛型版
- 非递归遍历,使用stack(FILO)。为什么不使用queue(FIFO)?广度优先(Breadth-First)选queue,深度优先(Depth-first)选队列。
- 后序遍历,我们使用两个stack,一个先序stack,一个后序stack,先序statck的出栈顺序即是后序stack的进栈顺序。另外一种方法是使用访问flag。定义一个node wrapper类,增加isVisit属性;在while中使用peek操作获得栈顶元素,如果被访问,则出栈,调用visit方法;没有被访问,则将子节点压栈,标记已访问
- 使用泛型声明,这样这个class被可以访问任意具体Tree结构的class
如何传递参数和返回结果?
- 使用java inner class 或者 anonymous class 来定义NodeVisitor子类,这样在NodeVisitor的visit方法中可以访问外部closures类的属性
使用如下:
需要定义为final类型,否则anonymous class无法访问
java内部突破java思维,几下几点可给力
- 泛型(generic)
- 反射(reflection)
- closures(inner/anonymous class)
- 注解(annotation)