日期:2014-05-16 浏览次数:20501 次
我们通常会在应用中碰到树形结构的内容,比如 文件夹/文件模型, 部门组织结构,目录树等等,通常在设计模式中叫做 compose 模式。 
在数据库中常常这样表示: 我们以Catalog (分级目录) 为例子
| 
 Catalog (分级目录)  | 
|||
| 
 字段名称  | 
 字段  | 
 类型  | 
 备注  | 
| 
 目录ID  | 
 catalog_id  | 
 varchar(36)  | 
 pk, not null  | 
| 
 目录名称  | 
 catalog_name  | 
 varchar(50)  | 
 not null  | 
| 
 父目录ID  | 
 parent_id  | 
 varchar(36)  | 
 fk  | 
| 
 创建时间  | 
 create_datetime  | 
 datetime  | 
 not null  | 
| 
 目录描述  | 
 description  | 
 varchar(200)  | 
? | 
我们考虑在数据库中一次将所有数据读入内存,然后在内存中生成一个Tree,这样可以减少数据库的访问,增加性能,并且只有的数据方式改变的时候,全部重新从数据库中生成Tree,否则一直保持在内存中。 
我们使用标准的DAO模式先生成 POJO类(Catalog)和DAO类(CatalogDAO)。 
然后我们建立相对通用的 Tree 和 TreeNode 类。 
Tree.java
package com.humpic.helper.tree;
import java.util.*;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public abstract class Tree {
    protected static Log log = LogFactory.getLog(Tree.class);
    private Map treeNodeMaps = new Hashtable();
    private TreeNode root;
    /**
     * root if it's parent is empty
     */
    protected void reload(List nodes) {
        log.info("tree will start reload all data");
        
        synchronized (this) {
            // initialize
            treeNodeMaps.clear();
            root = null;
            List treeNodes = new Vector(nodes.size());
            for (int i = 0; i < nodes.size(); i++) {
                TreeNode node = this.transform(nodes.get(i)); // transform
                treeNodes.add(node);
                node.setTree(this);
                treeNodeMaps.put(node.getNodeId(), node);
            }
            
            for (int i = 0; i < treeNodes.size(); i++) {
                TreeNode node = (TreeNode) treeNodes.get(i);
                String parentId = node.getParentId();
                if (this.isRootNode(node)) {
                    if (root == null) {
                        root = node;
                    } else {
                        log.error("find more then one root node. ignore.");
                    }
                } else {
                    T