访问者模式
前言
- 定义
表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变个元素的类的前提下定义作用于这些元素的新操作 - 核心
对于存储在一个集合中的对象,他们可能具有不同的类型(即使有一个公共的接口),对于该集合中的对象,可以接受一类称为访问者的对象来访问,不同的访问者其访问方式也有所不同。 - 结构
访问者(Visitor):为该对象结构中的具体元素角色声明一个访问操作接口。
具体访问者(Concrete Visitor):实现每个由访问者角色访问的操作。
元素角色(Element):定义一个Accept操作,它以一个访问者为参数。
具体元素角色(Concrete Element):实现由元素角色提供的Accept操作。
对象结构角色(Object Structure):能枚举它的元素;可以提供一个高层的接口以允许访问者访问它的元素;可以是一个复合或者一个集合,如一个列表或无序集合。
一、具体实现
1.访问者接口
public interface Visitor {
/**
* 对应NodeA的访问操作
*/
public void visit(NodeA node);
/**
* 对应NodeB的访问操作
*/
public void visit(NodeB node);
}
2.具体访问者类
public class VisitorA implements Visitor {
@Override
public void visit(NodeA node) {
System.out.println(node.operationA());
}
@Override
public void visit(NodeB node) {
System.out.println(node.operationB());
}
}
public class VisitorB implements Visitor {
@Override
public void visit(NodeA node) {
System.out.println(node.operationA());
}
@Override
public void visit(NodeB node) {
System.out.println(node.operationB());
}
}
3.抽象元素类
public abstract class Node {
/**
* 接受操作
*/
public abstract void accept(Visitor visitor);
}
4.具体元素类
public class NodeA extends Node {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
/**
*NodeA 特有方法
*/
public String operationA(){
return "NodeA";
}
}
public class NodeB extends Node {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
/**
*NodeB 特有方法
*/
public String operationB(){
return "NodeB";
}
}
5.对象结构角色
import java.util.ArrayList;
import java.util.List;
public class ObjectStructure {
private List<Node> nodes = new ArrayList<>();
/**
* 执行方法操作
*/
public void action(Visitor visitor){
for(Node node :nodes){
node.accept(visitor);
}
}
/**
* 添加一个新元素
*/
public void add(Node node){
nodes.add(node);
}
}
6.测试类
public class Client {
public static void main(String[] args) {
//创建一个结构对象
ObjectStructure objectStructure = new ObjectStructure();
//给结构增加一个节点
objectStructure.add(new NodeA());
//给结构增加一个节点
objectStructure.add(new NodeB());
//创建一个访问者
VisitorA visitorA = new VisitorA();
objectStructure.action(visitorA);
}
}
结果:
二、应用场景
- XML文档解析器设计
- 编译器的设计
- 复杂集合对象的处
总结
- 优点
1.访问者模式使得增加新的操作变得容易。
2.访问者模式可以跨过几个类的等级结构访问属于不同等级结构的成员类。
3.访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点。
4.积累状态。 - 缺点
1.增加新的节点变得很困难。
2.破坏了封装。 - 场景
1.一个对象结构包含很多类对象,它们有不同的接口,而我们想对这些对象实施一些依赖于其具体类的操作。
2.需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而我们想避免让这些操作“污染”这些对象的类。
3.当对象结构被很多应用共享时,Visitor模式让每一个应用仅包含需要用到的操作。
4.定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。