一、 访问者(Visitor)模式的结构
访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
根据对象的类型而对方法进行的选择称为分派(Dispatch)。一个方法所属的对象叫做方法的接收者,方法的接收者与方法的参量统称做方法的宗量。根据分派可以基于多少种宗量,可以将面向对象语言划分为单分派语言和多分派语言。单分派语言根据一个宗量的类型进行对方法的选择,多分派语言根据多于一个宗量的类型对方法进行选择。C++和Java均是单分派语言,C++和Java是动态的单分派语言,因为这两种语言的动态分派仅仅会考虑到方法的接收者的类型,同时又是静态的多分派语言,因为这两种语言对重载方法的分派会考虑到方法的接收者的类型以及方法的所有参量的类型。
结构图如下所示:
代码如下:
//Visitor接口
public interface Visitor{
void visit(NodeA node);
void visit(NodeB node);
}
//VisitorA类
public class VisitorA implements Visitor{
public void visit(NodeA nodeA){
System.out.println(nodeA.opertionA);
}
public void visit(NodeB nodeB){
System.out.println(nodeB.operationB());
}
}
//Node抽象类
abstract public class Node{
public abstract void accept(Visitor visitor);
}
//NodeA类
public class NodeA extends Node{
public void accept(Visitor visitor){
visitor.visit(this);
}
public String operationA(){
return “NodeA is visited”;
}
}
//NodeB类
public class NodeB extends Node{
public void accept(Visitor visitor){
visitor.visit(this);
}
public String operationB(){
return “NodeB is visited”;
}
}
//ObjectStructure类
public class ObjectStructure{
private Vector nodes;
private Node node;
public ObjectStructure(){
nodes = new Vector();
}
public void action(Visitor visitor){
for(Enumeration e = nodes.elements();e.hasMoreElements();){
node = (Node)e.nextElement();
node.accept(visitor);
}
}
public void add(Node node){
nodes.addElement(node);
}
}
二、 访问者模式优缺点
优点
(1)、访问者模式使得增加新的操作变得容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。
(2)、访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
(3)、访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。
(4)、积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。
缺点
(1)、增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
(2)、破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。
适用情况
1、访问者模式仅应当在被访问的类结构非常稳定情况下使用。换言之,系统很少出现需要加入新节点的情况。如果出现需要加入新节点的情况,就必须在每一个访问对象里加入一个对应于这个新节点的访问操作,而这是对一个系统的大规模修改,因而违背了“开—闭”原则的。
三、 访问者模式与其他模式的关系
迭代模式
迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。而访问者模式可以
合成模式
访问者模式常常浏览符合合成模式的一些结构对象。