访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接收这个操作的数据结构则可以保持不变。
访问者模式的组成结构:
1) 访问者角色(Visitor):为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。
2) 具体访问者角色(Concrete Visitor):实现每个由访问者角色(Visitor)声明的操作。
3) 元素角色(Element):定义一个Accept操作,它以一个访问者为参数。
4) 具体元素角色(Concrete Element):实现由元素角色提供的Accept操作。
5) 对象结构角色(Object Structure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合。
如何让访问者模式跑起来?
首先在原有的类层次结构中添加accept方法,然后将这个类层次中的类放到一个对象结构中去,这样再创建访问者角色...
public interface Node {
/**
* 接收操作
*/
public void accept(Visitor visitor);
}
public class NodeA implements Node {
/**
* 接收操作
*/
public void accept(Visitor visitor) {
visitor.visitor(this);
}
/**
* NodeA特有的商业方法,visitor就是对其进行封装
*/
public void operationA() {
System.out.println("NodeA operation");
}
}
public class NodeB implements Node {
/**
* 接收操作
*/
public void accept(Visitor visitor) {
visitor.visitor(this);
}
/**
* NodeB特有的商业方法,visitor就是对其进行封装
*/
public void operationB() {
System.out.println("NodeB operation");
}
}
public interface Visitor {
/**
* 对应于NodeA的访问操作
*/
public void visitor(NodeA node);
/**
* 对应于NodeB的访问操作
*/
public void visitor(NodeB node);
}
public class VisitorA implements Visitor {
/**
* 对应于NodeA的访问操作
*/
public void visitor(NodeA node) {
node.operationA();
}
/**
* 对应于NodeB的访问操作
*/
public void visitor(NodeB node) {
node.operationB();
}
}
public class VisitorB implements Visitor {
/**
* 对应于NodeA的访问操作
*/
public void visitor(NodeA node) {
node.operationA();
}
/**
* 对应于NodeB的访问操作
*/
public void visitor(NodeB node) {
node.operationB();
}
}
/**
* 结构对象
*/
public class ObjectStructure {
private Vector<Node> nodes = new Vector<Node>();
private Node node;
/**
* 执行访问操作
*/
public void action(Visitor visitor) {
for (Node node : nodes) {
node.accept(visitor);
}
}
/**
* 增加一个新的元素
*/
public void add(Node node) {
nodes.addElement(node);
}
}
public class Client {
public static void main(String[] args) {
//创建一个结构对象
ObjectStructure objectStructure = new ObjectStructure();
//给结构增加一个节点
objectStructure.add(new NodeA());
//给结构增加一个节点
objectStructure.add(new NodeB());
//创建一个新访问者
Visitor visitor = new VisitorA();
//让访问者访问结构
objectStructure.action(visitor);
}
}
双重分派
首先在客户程序中将具体访问者模式作为参数传递给具体元素角色,这便完成了一次分派。
进入具体元素角色后,具体元素角色调用作为参数的具体访问者模式中的visitor方法,同时将自己(this)作为参数传递进去。具体访问者模式再根据参数的不同来选择方法来执行,这便完成了第二次分派。
《设计模式》一书中给出了访问者模式适用的情况:
1) 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2) 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。
3) 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
4) 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
本文介绍了访问者模式的目的、组成结构及其实现方式。访问者模式适用于需要对多种类对象实施依赖于其具体类的操作场景。文章还提供了具体的代码示例,并讨论了模式的适用条件。
1753

被折叠的 条评论
为什么被折叠?



