随笔 - 1  文章 - 1  trackbacks - 0
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(1)

随笔分类

随笔档案

文章分类

文章档案

搜索

  •  

最新评论

◎ 节点类的设计
   ·特征分析
       数据特征:名字、节点值、节点的属性、节点的父节点、节点下的子节点、参照对象等特点
       行为特征:得到节点名、节点值、子节点、节点的属性、参照对象
                 增加子节点、属性、参照对象
                 删除子节点、属性
                 设置父节点
                 判断节点是否为空(没有值且没有子节点和属性)
                 遍历节点及节点下的所有子节点(以及子节点下的子节点)
                 对于像子节点、属性这类可以有多个对象的数据,应提供
                     根据名字获取节点集合的操作;获取所有节点集合的操作;获取某位置的节点;遍历所有节点;获取集合数量
             另外,子节点和节点具有共同的特征,只是子节点是节点的集合,如上所述,同时子节点有一些集合所特有的操作;
             属性则是节点的一个子集,具有名字、值、父节点,可以当作节点来处理。
   ·类设计
      节点类Node
     子节点类SubNodes
     另外为了在遍历过程中,可以针对所遍历的每个节点执行自定义的动作,提供NodeVisit接口
      同时提供NodeVisit接口的适配NodeVisitAdaptor
   ·遍历的问题
     首先执行节点的访问Node.visit,然后在Node.visit方法中调用子节点SubNodes.visit方法,在SubNodes.visit方法中对集合中的
     所有节点(Node),调用Node.visit,这样就实现了给定节点及该节点下面所有节点的遍历。
     原理:实际上是一种互调。即在A类对象中调用B类对象的方法,同时又在B类对象的同一个方法中调用A类对象的方法。
           A类和B类的约束,A类包含一个B类对象,B类包含了A类对象的集合,A类对象和B类对象拥有同样的调用方法visit(也可以是其它名字)。
           这样当A调用B的方法时,B遍历所有的A并调用A的方法,由此实现了遍历访问。
           最后,请记住遍历的对象应该是相同的类对象。
   ·框架
     public class Node{
        private String ms_Name;
        private Object mo_Value;
        private SubNodes msn_Children;
        private SubNodes msn_Attributes;
        public String getName();
        public Object getValue();
        public void setParentNode(Node);
        public void addChild(Node);
        public int getChildrenCount();
        public int getChildrenCount(String childName)
        public List getChildren();
        public List getChildren(String childName);
        public Node getChild(int index);
        public boolean removeChild(Node);
        public boolean removeChildren(String childName);
        public boolean removeChildren();
        public void addAttribute(Node);
        public int getAttributeCount();
        public int getAttributeCount(String attrName)
        public List getAttributes();
        public List getAttributes(String attrName);
        public Node getAttribute(int index);
        public boolean removeAttribute(Node);
        public boolean removeAttributes(String attrName);
        public boolean removeAttributes();
        public boolean isAttribute();//检查节点是否是一个属性节点
        public boolean isDefined();//节点是否定义过,即节点有值或有子节点
        public void visit(NodeVisit);
        protected static class SubNodes{
            private List ml_nodes;//子节点
            private Map mm_namedNodes;//子节点名字与子节点链表的映射,即多个子节点可以有相同的名字
            public void addNode(Node);
            public boolean removeNode(Node);
            public boolean removeNodes(String);
            public void clear();
            public ConfigurationNode getNode(int index);
            public List getSubNodes();//返回所有子节点
            public List getSubNodes(String name);
            public void visit(NodeVisit)
        }
} public interface NodeVisitor{ void visitBeforeChildren(ConfigurationNode node);//在该节点的所有子节点被处理之前,访问该节点 void visitAfterChildren(ConfigurationNode node);//在该节点的所有子节点被处理之后,访问该节点 boolean terminate();//结束标识,通知访问方法是否结束。通过该标识,可以实现某种搜索策略。 } ·Jarkarta开源的实现片段 public class DefaultConfigurationNode implements ConfigurationNode, Cloneable{ public void addChild(ConfigurationNode child)//增加子节点 { children.addNode(child); child.setAttribute(false); child.setParentNode(this);//设置父节点 } public void addAttribute(ConfigurationNode attr){//增加属性 attributes.addNode(attr); attr.setAttribute(true); attr.setParentNode(this); } public boolean isAttribute(){//节点是否是属性节点 return attribute; } public void setAttribute(boolean f){//设置节点是否是属性节点 checkState(); attribute = f; } public boolean isDefined(){//节点是否已经定义 return getValue() != null || getChildrenCount() > 0 || getAttributeCount() > 0; } public void visit(ConfigurationNodeVisitor visitor){//遍历节点 if (visitor == null){ throw new IllegalArgumentException("Visitor must not be null!"); } if (!visitor.terminate()){ visitor.visitBeforeChildren(this);//执行自定义访问动作 children.visit(visitor);//调用子节点的visit,从而实现了该节点下面所有节点的遍历 attributes.visit(visitor); visitor.visitAfterChildren(this);//执行自定义访问动作 } } public Object clone(){//浅克隆,因为克隆后子节点和属性都进行了初始化 try{ DefaultConfigurationNode copy = (DefaultConfigurationNode) super .clone(); copy.initSubNodes(); return copy; }catch (CloneNotSupportedException cex){ return null; // should not happen } } protected void checkState(){ if (getParentNode() != null){ throw new IllegalStateException( "Node cannot be modified when added to a parent!"); } } protected SubNodes createSubNodes(boolean attributes){//创建子节点 return new SubNodes(); } private void initSubNodes(){//初始化子节点和属性 children = createSubNodes(false); attributes = createSubNodes(true); } protected static class SubNodes{//内部类,帮助DefaultConfigurationNode管理子节点 private List nodes; private Map namedNodes; public void addNode(ConfigurationNode node){//增加一个子节点 if (node == null || node.getName() == null){ throw new IllegalArgumentException( "Node to add must have a defined name!"); } node.setParentNode(null); //设置为空,由DefaultConfigurationNode的addChild来完成setParent if (nodes == null){ nodes = new ArrayList(); namedNodes = new HashMap(); } nodes.add(node); List lst = (List) namedNodes.get(node.getName()); if (lst == null){ lst = new LinkedList();//链表结构 namedNodes.put(node.getName(), lst); } lst.add(node); } public boolean removeNode(ConfigurationNode node){//删除一个子节点 if (nodes != null && node != null && nodes.contains(node)){ detachNode(node); nodes.remove(node); List lst = (List) namedNodes.get(node.getName()); if (lst != null){ lst.remove(node); if (lst.isEmpty()){ namedNodes.remove(node.getName()); } } return true; }else{ return false; } } public boolean removeNodes(String name){//清除所有名字为name的子节点 if (nodes != null && name != null){ List lst = (List) namedNodes.remove(name); if (lst != null){ detachNodes(lst); nodes.removeAll(lst); return true; } } return false; } public void clear(){//清除所有子节点 if (nodes != null){ detachNodes(nodes); nodes = null; namedNodes = null; } } public ConfigurationNode getNode(int index){//取第index个子节点index从0开始 if (nodes == null) { throw new IndexOutOfBoundsException("No sub nodes available!"); } return (ConfigurationNode) nodes.get(index); } public List getSubNodes(){//取所有子节点 return (nodes == null) ? Collections.EMPTY_LIST : Collections .unmodifiableList(nodes); } public List getSubNodes(String name){//取所有名字为name的子节点 if (name == null){//如果name为空返回所有子节点 return getSubNodes(); } List result; if (nodes == null){ result = null; }else{ result = (List) namedNodes.get(name); } return (result == null) ? Collections.EMPTY_LIST : Collections .unmodifiableList(result); } public void visit(ConfigurationNodeVisitor visitor){//遍历所有子节点 if (nodes != null) { for (Iterator it = nodes.iterator(); it.hasNext() && !visitor.terminate();) { ((ConfigurationNode) it.next()).visit(visitor);//通过与Node的配合实现了遍历功能 } } } //删除一个子节点时调用此方法,确保被删除节点的父对象被置空(reset),同时清除被删除节点所有的引用 protected void detachNode(ConfigurationNode subNode){ subNode.setParentNode(null); if (subNode instanceof DefaultConfigurationNode){ ((DefaultConfigurationNode) subNode).removeReference(); } } protected void detachNodes(Collection subNodes){ for (Iterator it = subNodes.iterator(); it.hasNext();){ detachNode((ConfigurationNode) it.next()); } } } } ·遍历调用的例子 protected static void clearReferences(ConfigurationNode node){//清除所有的引用 node.visit(new ConfigurationNodeVisitorAdapter(){//匿名实现 public void visitBeforeChildren(ConfigurationNode nodeClearRef){ nodeClearRef.setReference(null); } }); }
posted on 2009-02-24 15:30 小桥流水人家 阅读(732) 评论(0)  编辑  收藏 所属分类: java

只有注册用户登录后才能发表评论。


网站导航: