dom4j遍歷xml文檔樹有種很特別的方式就是訪問者(Visitor)模式,初次接觸Visitor模式,寫出個人理解大家交流!
Visitor訪問者模式定義:作用于某個對象樹中各個對象的操作. 它可以使你在不改變這些對象樹本身的情況下,定義作用于這些對象樹各個節點的新操作。
先看以下代碼:Person為簡單的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()
{


/**//*
* 準備數據-String對象-Person對象-Integer對象-List對象
*/
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中的每一個對象并打印
*/

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

/**//*
* 增強的for循環
*/

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


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

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


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

public interface Visitable
{
public void accept(Visitor visitor);
}
下來是四個被訪問的類型String,Integer,Person,Collection的實現類
package org.bulktree.visitor;


/** *//**
* 被訪問者--String對象
* @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;


/** *//**
* 被訪問者--Integer對象
* @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;


/** *//**
* 被訪問者--Person對象
* @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;


/** *//**
* 被訪問者--Collection對象
* @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);
}
}

下來定義一個訪問者Visitor接口,它可以訪問Integer,String,Person(VO對象),Collection類型
package org.bulktree.visitor;

import java.util.Collection;


/** *//**
* 訪問者接口
* @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);
}
關鍵的Visitor實現類
package org.bulktree.visitor;

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


/** *//**
* 訪問者實現類
* @author bulktree Email: laoshulin@gmail.com
* @date Aug 10, 2008
*/

public class VisitorImpl implements Visitor
{


/**//*
*訪問字符串,僅對字符串輸出
*/

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


/** *//**
* 訪問Integer類型
*/

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


/** *//**
* 訪問Collection對象,遍歷每一個元素
* 使用了一個if語句判斷屬于Visitable哪一個被訪問對象,然后調用相應的accept方法
* 實現遞歸調用
*/

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

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

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


/** *//**
* 訪問單個Person對象
*/

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

}

客戶端測試:
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();


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


/**//*
* 訪問集合
*/
System.out.println("=======================訪問集合========================");
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);


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

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

使用訪問者模式的前提是對象群結構中(Collection) 中的對象類型很少改變,在兩個接口Visitor(訪問)和Visitable(可訪問)中,確保Visitable很少變化,也就是說,確保不能有新的元素類型加進來,可以變化的是訪問者行為或操作,也就是Visitor的不同子類可以有多種,這樣使用訪問者模式最方便,當系統中存在著固定的數據結構,且有著不同的行為,訪問者模式也許是個不錯的選擇
posted on 2008-08-10 12:12
凌晨風 閱讀(2139)
評論(2) 編輯 收藏 所屬分類:
Java學習筆記