dom4j遍历xml文档树有种很特别的方式就是访问者(Visitor)模式,初次接触Visitor模式,写出个人理解大家交流!
Visitor访问者模式定义:作用于某个对象树中各个对象的操作. 它可以使你在不改变这些对象树本身的情况下,定义作用于这些对象树各个节点的新操作。
先看以下代码:Person为简单的vo类
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
*
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class ReadCollection
{
![](/Images/OutliningIndicators/InBlock.gif)
private Collection c = null;
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
ReadCollection()
{
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
* 准备数据-String对象-Person对象-Integer对象-List对象
*/
String str = "bulktree.laoshulin";
Person person = new Person("bulktree", "22", "M");
Integer a = new Integer(99);
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
* 使用范型
*/
List<String> list = new ArrayList<String>();
list.add("BULKTREE");
list.add("LAOSHULIN");
list.add("OAKERTREE");
![](/Images/OutliningIndicators/InBlock.gif)
c = new ArrayList();
c.add(str);
c.add(person);
c.add(a);
c.add(list);
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 遍历Collection中的每一个对象并打印
*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void testCollection()
{
Iterator iter = getCollection().iterator();
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (iter.hasNext())
{
Object o = iter.next();
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (o instanceof String)
{
System.out.println("String--> " + o.toString());
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} else if (o instanceof Person)
{
readPerson((Person) o);
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} else if (o instanceof Integer)
{
Integer inta = (Integer) o;
System.out.println(inta.intValue());
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} else if (o instanceof List)
{
readList((List) o);
}
}
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Collection getCollection()
{
return c;
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void readPerson(Person person)
{
System.out.println("person-name-> " + person.getName());
System.out.println("person-age-> " + person.getAge());
System.out.println("person-sex-> " + person.getSex());
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void readList(List<String> list)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
* 增强的for循环
*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for (String s : list)
{
System.out.println(s);
}
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String[] args)
{
new ReadCollection().testCollection();
}
}
![](/Images/OutliningIndicators/None.gif)
我们使用了 instanceof来判断 Object对象 o 的类型,这样做的缺点是代码中If/else if 很繁琐,而JDK中的范型又限制了只能使用相同的类型,这时Vistor访问模式派上用场了。
当我们要访问Collection的每一个Element(被访问者)时,定义一个accept操作使其具有可被访问性,我们定义一个Visiable接口,使Collection的每一个Element继承这个接口,实现自身的访问操作
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
* 可访问性--接收一个访问者
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public interface Visitable
{
public void accept(Visitor visitor);
}
下来是四个被访问的类型String,Integer,Person,Collection的实现类
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
* 被访问者--String对象
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class StringElement implements Visitable
{
![](/Images/OutliningIndicators/InBlock.gif)
private String str;
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public StringElement(String str)
{
this.str = str;
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String getStr()
{
return str;
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void accept(Visitor visitor)
{
visitor.visitString(this);
}
}
![](/Images/OutliningIndicators/None.gif)
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
* 被访问者--Integer对象
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class IntegerElement implements Visitable
{
![](/Images/OutliningIndicators/InBlock.gif)
private Integer i;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public IntegerElement(Integer i)
{
this.i = i;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Integer getI()
{
return i;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void accept(Visitor visitor)
{
visitor.visitInteger(this);
![](/Images/OutliningIndicators/InBlock.gif)
}
}
![](/Images/OutliningIndicators/None.gif)
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
import java.util.Collection;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
* 被访问者--Person对象
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class PersonElement implements Visitable
{
private Person p;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public PersonElement(Person p)
{
this.p = p;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Person getP()
{
return p;
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void accept(Visitor visitor)
{
visitor.visitPerson(this);
}
}
![](/Images/OutliningIndicators/None.gif)
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
import java.util.Collection;
import java.util.List;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
* 被访问者--Collection对象
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class CollectionElement implements Visitable
{
![](/Images/OutliningIndicators/InBlock.gif)
private Collection collection;
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public CollectionElement(Collection collection)
{
this.collection = collection;
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Collection getCollection()
{
return collection;
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void accept(Visitor visitor)
{
visitor.visitCollection(collection);
}
}
![](/Images/OutliningIndicators/None.gif)
下来定义一个访问者Visitor接口,它可以访问Integer,String,Person(VO对象),Collection类型
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
import java.util.Collection;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
* 访问者接口
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public interface Visitor
{
public void visitString(StringElement str);
public void visitInteger(IntegerElement i);
public void visitCollection(Collection collection);
public void visitPerson(PersonElement perE);
}
关键的Visitor实现类
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
import java.util.Collection;
import java.util.Iterator;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
* 访问者实现类
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class VisitorImpl implements Visitor
{
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
*访问字符串,仅对字符串输出
*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void visitString(StringElement str)
{
System.out.println("*******************字符串输出*************************");
System.out.println(str.getStr());
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 访问Integer类型
*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void visitInteger(IntegerElement i)
{
System.out.println("*******************整型输出*************************");
System.out.println(i.getI());
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 访问Collection对象,遍历每一个元素
* 使用了一个if语句判断属于Visitable哪一个被访问对象,然后调用相应的accept方法
* 实现递归调用
*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void visitCollection(Collection collection)
{
Iterator iter = collection.iterator();
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (iter.hasNext())
{
Object o = iter.next();
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (o instanceof Visitable)
{
((Visitable) o).accept(this);
}
}
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 访问单个Person对象
*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void visitPerson(PersonElement perE)
{
System.out.println("*******************Person对象输出*************************");
Person person = perE.getP();
System.out.println("person-name-> " + person.getName());
System.out.println("person-age-> " + person.getAge());
System.out.println("person-sex-> " + person.getSex());
}
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/None.gif)
客户端测试:
package org.bulktree.visitor;
![](/Images/OutliningIndicators/None.gif)
import java.util.ArrayList;
import java.util.Collection;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//**
* Visitor模式客户端
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class VisitorMain
{
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String[] args)
{
Visitor visitor = new VisitorImpl();
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
* 访问字符串
*/
System.out.println("======================访问字符串=========================");
StringElement stringE = new StringElement(
"bulktree.laoshulin.oakertree");
visitor.visitString(stringE);
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
* 访问集合
*/
System.out.println("=======================访问集合========================");
Collection list = new ArrayList();
![](/Images/OutliningIndicators/InBlock.gif)
StringElement str1 = new StringElement("aaa");
StringElement str2 = new StringElement("bbb");
list.add(str1);
list.add(str2);
PersonElement perE1 = new PersonElement(new Person("LAOSHULIN", "22", "M"));
PersonElement perE2 = new PersonElement(new Person("BULKTREE", "21", "W"));
list.add(perE1);
list.add(perE2);
IntegerElement intE1 = new IntegerElement(new Integer(99));
IntegerElement intE2 = new IntegerElement(new Integer(100));
list.add(intE1);
list.add(intE2);
visitor.visitCollection(list);
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
* 访问Person
*/
System.out.println("======================访问Person=========================");
Person p = new Person("BULKTREE", "22", "M");
PersonElement perE = new PersonElement(p);
visitor.visitPerson(perE);
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
* 访问Integer
*/
System.out.println("=====================访问Integer==========================");
IntegerElement intE = new IntegerElement(new Integer(77));
visitor.visitInteger(intE);
}
}
![](/Images/OutliningIndicators/None.gif)
使用访问者模式的前提是对象群结构中(Collection) 中的对象类型很少改变,在两个接口Visitor(访问)和Visitable(可访问)中,确保Visitable很少变化,也就是说,确保不能有新的元素类型加进来,可以变化的是访问者行为或操作,也就是Visitor的不同子类可以有多种,这样使用访问者模式最方便,当系统中存在着固定的数据结构,且有着不同的行为,访问者模式也许是个不错的选择
posted on 2008-08-10 12:12
凌晨风 阅读(2133)
评论(2) 编辑 收藏 所属分类:
Java学习笔记