◎ 节点类的设计
·特征分析
数据特征:名字、节点值、节点的属性、节点的父节点、节点下的子节点、参照对象等特点
行为特征:得到节点名、节点值、子节点、节点的属性、参照对象
增加子节点、属性、参照对象
删除子节点、属性
设置父节点
判断节点是否为空(没有值且没有子节点和属性)
遍历节点及节点下的所有子节点(以及子节点下的子节点)
对于像子节点、属性这类可以有多个对象的数据,应提供
根据名字获取节点集合的操作;获取所有节点集合的操作;获取某位置的节点;遍历所有节点;获取集合数量
另外,子节点和节点具有共同的特征,只是子节点是节点的集合,如上所述,同时子节点有一些集合所特有的操作;
属性则是节点的一个子集,具有名字、值、父节点,可以当作节点来处理。
·类设计
节点类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