1. 什么是访问者模式?
访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问者两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。
访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为“对象结构”,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。
2. 角色
图片来源于网络
抽象访问者(Visitor):声明了一个或者多个方法操作,形成所有的具体访问者角色必须实现的接口。
具体访问者(ConcreteVisitor):实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象节点(Node):声明一个接受操作,接受一个访问者对象作为一个参数。
具体节点(ConcreteNode):实现了抽象节点所规定的接受操作。
结构对象(ObjectStructure):有如下的责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如List或Set。
3. 优点
(1)好的扩展性。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
(2)好的复用性。可以通过访问者来定义整个对象结构通用的功能,从而提高复用程度。
(3)分离无关行为。可以通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。
4. 缺点
(1)对象结构变化很困难。不适用于对象结构中的类经常变化的情况,因为对象结构发生了改变,访问者的接口和访问者的实现都要发生相应的改变,代价太高。
(2)破坏封装。访问者模式通常需要对象结构开放内部数据给访问者和ObjectStructrue,这破坏了对象的封装性。
5. 使用场景
(1)对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
(2)需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
6. 示例代码
(1)抽象访问者
/**
* 抽象访问者类
*/
public interface Visitor {
//对NodeA的访问操作
public void visit(NodeA nodeA);
//对NodeB的访问操作
public void visit(NodeB nodeB);
}
(2)具体访问者
/**
* 具体的访问者A
*/
public class VisitorA implements Visitor {
@Override
public void visit(NodeA nodeA) {
System.out.println(nodeA.operationA());
}
@Override
public void visit(NodeB nodeB) {
System.out.println(nodeB.operationB());
}
}
/**
* 具体的访问者B
*/
public class VisitorB implements Visitor {
@Override
public void visit(NodeA nodeA) {
System.out.println(nodeA.operationA());
}
@Override
public void visit(NodeB nodeB) {
System.out.println(nodeB.operationB());
}
}
(3)抽象节点
/**
* 抽象节点类
*/
public abstract class Node {
//接收操作
public abstract void accept(Visitor visitor);
}
(4)具体节点
/**
* 具体的节点A
*/
public class NodeA extends Node {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationA(){
return "NodeA";
}
}
/**
* 具体的节点B
*/
public class NodeB extends Node {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationB(){
return "NodeB";
}
}
(5)结构对象
/**
* 结构对象角色类
*/
public class ObjectStructure {
/**
* 保存节点对象
*/
private List<Node> list=new ArrayList<Node>();
/**
* 执行操作
*/
public void action(Visitor visitor){
for(Node node:list){
node.accept(visitor);
}
}
/**
* 添加一个新元素
*/
public void addNode(Node node){
list.add(node);
}
}
(6)测试
public class Client {
public static void main(String[] args) {
ObjectStructure os=new ObjectStructure();
os.addNode(new NodeA());
os.addNode(new NodeB());
os.action(new VisitorA());
}
}
(7)测试结果
NodeA
NodeB
转载自http://www.cnblogs.com/java-my-life/archive/2012/06/14/2545381.html
【四川乐山程序员联盟,欢迎大家加群相互交流学习5 7 1 8 1 4 7 4 3】