一個集合中有同一種類型的數據,他們或者繼承同一個父類,或者實現了同一個接口,但是他們各自的屬性和方法有時卻存在着差異,而這些數據一旦被添加進一些集合以後,他們的差異性就被一般化了,若需要再次取得這些具有“個性”的類的話,則要做大量如下的工作:
for(A a : collection){
if(a instance of B){
//.....
}else if(a instance of C){
//.....
}else ....
}
這樣的代碼就顯得異常的繁瑣,Visitor模式實際上就是在做與if else 相同的工作,但是他的代碼更加飄逸一點。
[size=x-large]2.接口定義[/size]
兩個主要接口:
~Visitor
public interface Visitor {
public void visit(StringElement s);
public void visit(IntElement n);
public void visit(DoubleElement d);
}
Visitor定義了不同類型的對象的訪問方法
~Visitable
public interface Visitable {
public void accept(Visitor visitor);
}
Visitable定義的是被訪問者接受訪問者(也就是實現了visitor)訪問的方法,如果實現visitable的對象accept了一個visitor對象,那麼visitable就會調用visitor中相應的visit的方法(通過函數重載來實現),做到對visitable內所有可被訪問的元素(同樣也是實現了visitable)的遍歷。(這話說的.....有點繞了...)
[size=x-large]3.具體實現類的函數定義如下:[/size]
三個實現了visitable接口的元素類:
public class IntElement implements Visitable{
private int value = 1;
public int getValue(){
return this.value;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class DoubleElement implements Visitable{
private double value = 1.1;
public double getValue(){
return this.value;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class StringElement implements Visitable{
private String value = "I'm String";
public String getValue(){
return this.value;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
同樣是實現了visitable的集合類,visitor對象被這個集合類accept後,visitor便可以以各自的方法來訪問這個集合中那些有“個性”的元素了
public class Elements implements Visitable{
private Collection<Visitable> col = new ArrayList();
public void addElement(Visitable v){
col.add(v);
}
public void accept(Visitor visitor) {
for(Visitable v : col){
v.accept(visitor);
}
}
}
主函數
public static void main(String args[]){
Elements es = new Elements();
es.addElement(new StringElement());
es.addElement(new IntElement());
es.addElement(new DoubleElement());
MyVisitor mv = new MyVisitor();
es.accept(mv);
}
運行結果:
element.StringElement:I'm String
element.IntElement:1
element.DoubleElement:1.1
先傳個uml圖上來,畫得有點難看而且又點不規範,但是大概的模型就是這樣的
[img]http://dl.iteye.com/upload/attachment/454090/88f370a2-7494-35c6-8da0-95cfc21cecf3.jpg[/img]
[size=x-large]4.寫在後面:[/size]
剛開始接觸到visitor模式時,的確有點不懂,後來是用到dom4j的時候,在解析xml文件時,發現dom4j對其提供的visitor模式支持非常好用,只需要創建一個visitor了實現類,給它幾個篩選條件,我就能從一個Element中獲得我想要的節點信息了,這是纔對visitor模式有了一個大概的瞭解。不懂沒關係,敲一敲就會明白的。