Visitor 定義

  作用于某個對象群中各個對象的操作。 它可以使你在不改變這些對象本身的情況下,定義作用于這些對象的新操作。

  在Java(Java教程 Java培訓 ) 中,Visitor 模式實際上是分離了collection 結構中的元素和對這些元素進行操作的行為。

  為何使用Visitor?

  Java 的Collection(包括Vector 和Hashtable)是我們最經常使用的技術,可是Collection好象是個黑色大染缸,本來有各種鮮明類型特征的對象一旦放入后,再取出時,這些類型就消失了。那么我們勢必要用If 來判斷,如:

  Iterator iterator = collection.iterator()

  while (iterator.hasNext()) {

  Object o = iterator.next();

  if (o instanceof Collection)

  messyPrintCollection((Collection)o);

  else if (o instanceof String)

  System.out.println(“‘”+o.toString()+“’”);

  else if (o instanceof Float)

  System.out.println(o.toString()+“f”);

  else

  System.out.println(o.toString());

  }

  在上例中,我們使用了 instanceof 來判斷 o 的類型。

  很顯然,這樣做的缺點代碼If else if 很繁瑣。我們就可以使用Visitor 模式解決它。

  如何使用Visitor?

  針對上例,我們設計一個接口visitor 訪問者:

  public interface Visitor

  {

  public void visitCollection(Collection collection);

  public void visitString(String string);

  public void visitFloat(Float float);

  }

  在這個接口中,將我們認為Collection 有可能的類的類型放入其中。

  有了訪問者,我們需要被訪問者,被訪問者就是我們Collection 的每個元素Element,我們要為這些Element 定義一個可以接受訪問的接口(訪問和被訪問是互動的,只有訪問者,被訪問者如果表示不歡迎,訪問者就不能訪問),我們定義這個接口叫Visitable, 用來定義一個Accept 操作,也就是說讓Collection 每個元素具備可訪問性。

  public interface Visitable

  {

  public void accept(Visitor visitor);

  }

  好了,有了兩個接口,我們就要定義他們的具體實現(Concrete class):

  public class ConcreteElement implements Visitable

  {

  private String value;

  public ConcreteElement(String string) {

  value = string;

  }

  //定義accept 的具體內容 這里是很簡單的一句調用

  public void accept(Visitor visitor) {

  visitor.visitString(this);

  }

  }

  再看看訪問者的Concrete 實現:

  public class ConcreteVisitor implements Visitor

  {

  //在本方法中,我們實現了對Collection 的元素的成功訪問

  public void visitCollection(Collection collection) {

  Iterator iterator = collection.iterator()

  while (iterator.hasNext()) {

  Object o = iterator.next();

  if (o instanceof Visitable)

  ((Visitable)o).accept(this);

  }

  public void visitString(String string) {

  System.out.println(“‘”+string+“’”);

  }

  public void visitFloat(Float float) {

  System.out.println(float.toString()+“f”);

  }

  }

  }

  在上面的visitCollection 我們實現了對Collection 每個元素訪問,只使用了一個判斷語句,只要判斷其是否可以訪問。

  至此,我們完成了Visitor 模式基本架構。

  使用Visitor 模式的前提

  對象群結構中(Collection) 中的對象類型很少改變,也就是說訪問者的身份類型很少改變,如上面中Visitor 中的類型很少改變,如果需要增加新的操作,比如上例中我們在ConcreteElement 具體實現外,還需要新的ConcreteElement2 ConcreteElement3.

  可見使用Visitor 模式是有前提的,在兩個接口Visitor 和Visitable 中,確保Visitor 很少變化,變化的是Visitable,這樣使用Visitor 最方便。

  如果Visitor 也經常變化, 也就是說,對象群中的對象類型經常改變,一般建議是,不如在這些對象類中逐個定義操作。但是Java 的Reflect 技術解決了這個問題。

  Reflect 技術是在運行期間動態獲取對象類型和方法的一種技術,具體實現參考Javaworld的英文原文.