posts - 262,  comments - 221,  trackbacks - 0
一、Visitor模式定义:

作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作.在Java中,Visitor模式实际上是分离了collection结构中的元素和对这些元素进行操作的行为.

二、Visitor模式构成:

Visitor模式由被访问者(Visitable)和访问者(Visitor)构成,两者之间是互动的关系,即双方必须提供接口供彼此访问。下面是Visitor模式的一个例子(参考自www.jdon.com)

·被访问者接口
public interface Visitable {

   
public void accept(Visitor visitor);
}


·被访问者接口实现类

public class StringElement implements Visitable {
   
private String value;

   
public StringElement(String string) {
      value 
= string;
   }


   
public String getValue(){
      
return value;
   }


   
// 定义accept的具体内容 这里是很简单的一句调用
   public void accept(Visitor visitor) {
      visitor.visitString(
this);  // 被访问者接受了一个访问者,把自己作为回调方法中的参数
   }

}

·访问者接口
public interface Visitor {
   
public void visitString(StringElement stringE);
   
public void visitFloat(FloatElement floatE);     
   
public void visitCollection(Collection collection); 
}


注:因为这里被访问对象的类型已经明确,所以方法的形参定义可以具体到接口实现类,而不需要用接口类型

·访问者接口实现类
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(StringElement stringE) {
      System.out.println(
"'"+stringE.getValue()+"'");
   }
 

   
public void visitFloat(FloatElement floatE){
      System.out.println(floatE.getValue().toString()
+"f");
   }
 
}

·客户端调用代码
Visitor visitor = new ConcreteVisitor();

StringElement stringE 
= new StringElement("I am a String");
visitor.visitString(stringE);

Collection list 
= new ArrayList();
list.add(
new StringElement("I am a String1")); 
list.add(
new StringElement("I am a String2")); 
list.add(
new FloatElement(new Float(12))); 
list.add(
new StringElement("I am a String3")); 
visitor.visitCollection(list);

作为Visitor模式中的被访问者,通常都需要定义一个setXxx和getXxx方法,为访问者访问时提供接口。或者像上例一样,采用Call-back机制。而访问者也需要提供相应的接口来接收被访问者,以输出其内容。

三、Visitor模式的优缺点

从这个例子就可以看出Visitor模式的一个缺点:对于集合中的所有类型元素,访问者必须穷举所有的可能方法,一旦元素的类型比较多,则访问者的类将显得比较庞大。

StringElement只是一个实现,可以拓展为更多的实现,整个核心奥妙在accept方法中,在遍历Collection时,通过相应的accept方法调用具体类型的被访问者。这一步确定了被访问者类型。

Visitor模式的一个优点体现在对集合元素的访问中:由于集合中的可访问元素都实现了Visitable接口,所以在迭代集合的过程中,我们可以将每个元素都看成是接口类型。
 
其次由于JAVA语言的多态性,虽然每个元素都是接口类型(Visitable),但每个元素的实现类不同,所以在调用accept方法时,虚拟机“知道”应该调起那个正确的方法(例如:集合中的一个String元素,会调用StringElement的accept方法)

Visitor对集合类型的访问过程:对集合进行迭代,将自身作为参数调用每个被访问者的accept方法,被访问者的accept方法也以自身为参数回调访问者的visitXxx方法。

四、Visitor模式的使用前提和注意点

使用访问者模式前提是对象群结构中(Collection) 中的对象类型很少改变。

在两个接口Visitor和Visitable中,确保Visitable很少变化,也就是说,确保不能老有新的Element元素类型加进来,可以变化的是访问者行为或操作,也就是Visitor的不同子类可以有多种,这样使用访问者模式最方便.

如果对象集合中的对象集合经常有变化, 那么不但Visitor实现要变化,Visistable也要增加相应行为,GOF建议是,不如在这些对象类中直接逐个定义操作,无需使用访问者设计模式。

--摘自www.jdon.com的《Visitor模式》 一节

原因:

如果Visitable中元素的类型是固定的或者很少变化的,那么即使Visitor中相应的访问行为发生改变了,对Visitable也没有影响。相反如果Visitable中元素的类型变化频繁,除了Visitable要增加新的类型,Visitor也要增加相应的visitXxx方法。所以说使用Visitor模式的一个前提是被访问者的类型很少改变



-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
posted on 2008-04-15 17:38 Paul Lin 阅读(4456) 评论(2)  编辑  收藏 所属分类: 模式与重构


FeedBack:
# re: 设计模式总结-Visitor模式
2008-05-11 16:04 | 无羽苍鹰
^^学习了  回复  更多评论
  
# re: 设计模式总结-Visitor模式
2009-03-06 13:07 | rrroger
jdon这篇文章也太老了,visitor的优缺点分析的都太浅薄,参考价值不大  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2008年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

常用链接

留言簿(21)

随笔分类

随笔档案

BlogJava热点博客

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜