dom4j遍歷xml文檔樹(shù)有種很特別的方式就是訪問(wèn)者(Visitor)模式,初次接觸Visitor模式,寫出個(gè)人理解大家交流!
Visitor訪問(wèn)者模式定義:作用于某個(gè)對(duì)象樹(shù)中各個(gè)對(duì)象的操作. 它可以使你在不改變這些對(duì)象樹(shù)本身的情況下,定義作用于這些對(duì)象樹(shù)各個(gè)節(jié)點(diǎn)的新操作。
先看以下代碼:Person為簡(jiǎn)單的vo類
package org.bulktree.visitor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;


/** *//**
*
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public class ReadCollection
{

private Collection c = null;


ReadCollection()
{


/**//*
* 準(zhǔn)備數(shù)據(jù)-String對(duì)象-Person對(duì)象-Integer對(duì)象-List對(duì)象
*/
String str = "bulktree.laoshulin";
Person person = new Person("bulktree", "22", "M");
Integer a = new Integer(99);

/**//*
* 使用范型
*/
List<String> list = new ArrayList<String>();
list.add("BULKTREE");
list.add("LAOSHULIN");
list.add("OAKERTREE");

c = new ArrayList();
c.add(str);
c.add(person);
c.add(a);
c.add(list);

}


/** *//**
* 遍歷Collection中的每一個(gè)對(duì)象并打印
*/

public void testCollection()
{
Iterator iter = getCollection().iterator();


while (iter.hasNext())
{
Object o = iter.next();


if (o instanceof String)
{
System.out.println("String--> " + o.toString());

} else if (o instanceof Person)
{
readPerson((Person) o);

} else if (o instanceof Integer)
{
Integer inta = (Integer) o;
System.out.println(inta.intValue());

} else if (o instanceof List)
{
readList((List) o);
}
}

}


public Collection getCollection()
{
return c;
}


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());
}


private void readList(List<String> list)
{

/**//*
* 增強(qiáng)的for循環(huán)
*/

for (String s : list)
{
System.out.println(s);
}
}


public static void main(String[] args)
{
new ReadCollection().testCollection();
}
}

我們使用了 instanceof來(lái)判斷 Object對(duì)象 o 的類型,這樣做的缺點(diǎn)是代碼中If/else if 很繁瑣,而JDK中的范型又限制了只能使用相同的類型,這時(shí)Vistor訪問(wèn)模式派上用場(chǎng)了。
當(dāng)我們要訪問(wèn)Collection的每一個(gè)Element(被訪問(wèn)者)時(shí),定義一個(gè)accept操作使其具有可被訪問(wèn)性,我們定義一個(gè)Visiable接口,使Collection的每一個(gè)Element繼承這個(gè)接口,實(shí)現(xiàn)自身的訪問(wèn)操作
package org.bulktree.visitor;


/** *//**
* 可訪問(wèn)性--接收一個(gè)訪問(wèn)者
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public interface Visitable
{
public void accept(Visitor visitor);
}
下來(lái)是四個(gè)被訪問(wèn)的類型String,Integer,Person,Collection的實(shí)現(xiàn)類
package org.bulktree.visitor;


/** *//**
* 被訪問(wèn)者--String對(duì)象
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public class StringElement implements Visitable
{

private String str;


public StringElement(String str)
{
this.str = str;
}


public String getStr()
{
return str;
}


public void accept(Visitor visitor)
{
visitor.visitString(this);
}
}

package org.bulktree.visitor;


/** *//**
* 被訪問(wèn)者--Integer對(duì)象
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public class IntegerElement implements Visitable
{

private Integer i;

public IntegerElement(Integer i)
{
this.i = i;
}

public Integer getI()
{
return i;
}

public void accept(Visitor visitor)
{
visitor.visitInteger(this);

}
}

package org.bulktree.visitor;

import java.util.Collection;


/** *//**
* 被訪問(wèn)者--Person對(duì)象
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public class PersonElement implements Visitable
{
private Person p;

public PersonElement(Person p)
{
this.p = p;
}

public Person getP()
{
return p;
}


public void accept(Visitor visitor)
{
visitor.visitPerson(this);
}
}

package org.bulktree.visitor;

import java.util.Collection;
import java.util.List;


/** *//**
* 被訪問(wèn)者--Collection對(duì)象
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public class CollectionElement implements Visitable
{

private Collection collection;


public CollectionElement(Collection collection)
{
this.collection = collection;
}


public Collection getCollection()
{
return collection;
}


public void accept(Visitor visitor)
{
visitor.visitCollection(collection);
}
}

下來(lái)定義一個(gè)訪問(wèn)者Visitor接口,它可以訪問(wèn)Integer,String,Person(VO對(duì)象),Collection類型
package org.bulktree.visitor;

import java.util.Collection;


/** *//**
* 訪問(wèn)者接口
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public interface Visitor
{
public void visitString(StringElement str);
public void visitInteger(IntegerElement i);
public void visitCollection(Collection collection);
public void visitPerson(PersonElement perE);
}
關(guān)鍵的Visitor實(shí)現(xiàn)類
package org.bulktree.visitor;

import java.util.Collection;
import java.util.Iterator;


/** *//**
* 訪問(wèn)者實(shí)現(xiàn)類
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public class VisitorImpl implements Visitor
{


/**//*
*訪問(wèn)字符串,僅對(duì)字符串輸出
*/

public void visitString(StringElement str)
{
System.out.println("*******************字符串輸出*************************");
System.out.println(str.getStr());
}


/** *//**
* 訪問(wèn)Integer類型
*/

public void visitInteger(IntegerElement i)
{
System.out.println("*******************整型輸出*************************");
System.out.println(i.getI());
}


/** *//**
* 訪問(wèn)Collection對(duì)象,遍歷每一個(gè)元素
* 使用了一個(gè)if語(yǔ)句判斷屬于Visitable哪一個(gè)被訪問(wèn)對(duì)象,然后調(diào)用相應(yīng)的accept方法
* 實(shí)現(xiàn)遞歸調(diào)用
*/

public void visitCollection(Collection collection)
{
Iterator iter = collection.iterator();

while (iter.hasNext())
{
Object o = iter.next();

if (o instanceof Visitable)
{
((Visitable) o).accept(this);
}
}
}


/** *//**
* 訪問(wèn)單個(gè)Person對(duì)象
*/

public void visitPerson(PersonElement perE)
{
System.out.println("*******************Person對(duì)象輸出*************************");
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());
}

}

客戶端測(cè)試:
package org.bulktree.visitor;

import java.util.ArrayList;
import java.util.Collection;


/** *//**
* Visitor模式客戶端
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public class VisitorMain
{


public static void main(String[] args)
{
Visitor visitor = new VisitorImpl();


/**//*
* 訪問(wèn)字符串
*/
System.out.println("======================訪問(wèn)字符串=========================");
StringElement stringE = new StringElement(
"bulktree.laoshulin.oakertree");
visitor.visitString(stringE);


/**//*
* 訪問(wèn)集合
*/
System.out.println("=======================訪問(wèn)集合========================");
Collection list = new ArrayList();

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);


/**//*
* 訪問(wèn)Person
*/
System.out.println("======================訪問(wèn)Person=========================");
Person p = new Person("BULKTREE", "22", "M");
PersonElement perE = new PersonElement(p);
visitor.visitPerson(perE);

/**//*
* 訪問(wèn)Integer
*/
System.out.println("=====================訪問(wèn)Integer==========================");
IntegerElement intE = new IntegerElement(new Integer(77));
visitor.visitInteger(intE);
}
}

使用訪問(wèn)者模式的前提是對(duì)象群結(jié)構(gòu)中(Collection) 中的對(duì)象類型很少改變,在兩個(gè)接口Visitor(訪問(wèn))和Visitable(可訪問(wèn))中,確保Visitable很少變化,也就是說(shuō),確保不能有新的元素類型加進(jìn)來(lái),可以變化的是訪問(wèn)者行為或操作,也就是Visitor的不同子類可以有多種,這樣使用訪問(wèn)者模式最方便,當(dāng)系統(tǒng)中存在著固定的數(shù)據(jù)結(jié)構(gòu),且有著不同的行為,訪問(wèn)者模式也許是個(gè)不錯(cuò)的選擇
posted on 2008-08-10 12:12
凌晨風(fēng) 閱讀(2145)
評(píng)論(2) 編輯 收藏 所屬分類:
Java學(xué)習(xí)筆記