定义:表示一个作用某对象结构中的各元素操作,该模式使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
定义说的很抽象。
现在我们假设有这样的逻辑:
现存两个节点Node1,Node2
现存两个访问者Visitor1,Visitor2
节点对应的访问者的逻辑是
Visitor1访问Node1打印节点名称并加1,同理访问Node2也是如此。
Visitor2访问Node1打印节点名称并加100,同理访问Node2也是如此。
代码如下:
package Test;
import java.util.List;
import com.td.util.ListUtils;
//拜访者
interface Visitor {
}
class Visitor1 implements Visitor {
}
class Visitor2 implements Visitor {
}
// 节点
interface Node {
void accept(Visitor visitor);
}
class Node1 implements Node {
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
if (visitor instanceof Visitor1) {
System.err.println("Node1" + 1);
}
if (visitor instanceof Visitor2) {
System.err.println("Node1" + 100);
}
}
}
class Node2 implements Node {
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
if (visitor instanceof Visitor1) {
System.err.println("Node2" + 1);
}
if (visitor instanceof Visitor2) {
System.err.println("Node2" + 100);
}
}
}
public class ObjectStructure {
private List<Node> nodes = ListUtils.newArrayList();
public void action(Visitor visitor) {
for (Node node : nodes) {
node.accept(visitor);
}
}
public void add(Node node) {
nodes.add(node);
}
public static void main(String[] args) {
ObjectStructure os = new ObjectStructure();
os.add(new Node1());
os.add(new Node2());
Visitor v1 = new Visitor1();
os.action(v1);
}
}
此时我们要加入第三个访问者,Visitor3,那么如何修改逻辑呢。代码修改如下,添加部分
class Visitor3 implements Visitor {
}
class Node1 implements Node {
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
if (visitor instanceof Visitor1) {
System.err.println("Node1" + 1);
}
if (visitor instanceof Visitor2) {
System.err.println("Node1" + 100);
}
if(visitor instanceof Visitor3){
System.err.println("Node1" + 10000);
}
}
}
class Node2 implements Node {
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
if (visitor instanceof Visitor1) {
System.err.println("Node2" + 1);
}
if (visitor instanceof Visitor2) {
System.err.println("Node2" + 100);
}
if(visitor instanceof Visitor3){
System.err.println("Node1" + 10000);
}
}
}
此时你会发现一个问题,添加一个访问者,每个节点的也要跟着修改,如果现在我们用访问者模式去构建这个逻辑
代码如下:
package Test;
import java.util.List;
import com.td.util.ListUtils;
//拜访者
interface Visitor {
void visit(Node1 node);
void visit(Node2 node);
}
class Visitor1 implements Visitor {
@Override
public void visit(Node1 node) {
// TODO Auto-generated method stub
System.err.println("Node1"+1);
}
@Override
public void visit(Node2 node) {
// TODO Auto-generated method stub
System.err.println("Node2"+1);
}
}
class Visitor2 implements Visitor {
@Override
public void visit(Node1 node) {
// TODO Auto-generated method stub
System.err.println("Node1"+100);
}
@Override
public void visit(Node2 node) {
// TODO Auto-generated method stub
System.err.println("Node2"+100);
}
}
// 节点
interface Node {
void accept(Visitor visitor);
}
class Node1 implements Node {
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
class Node2 implements Node {
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
public class ObjectStructure {
private List<Node> nodes = ListUtils.newArrayList();
public void action(Visitor visitor) {
for (Node node : nodes) {
node.accept(visitor);
}
}
public void add(Node node) {
nodes.add(node);
}
public static void main(String[] args) {
ObjectStructure os = new ObjectStructure();
os.add(new Node1());
os.add(new Node2());
Visitor v1 = new Visitor1();
os.action(v1);
}
}
此时我们要添加一个访问者,改如何修改代码呢,
代码如下:
class Visitor3 implements Visitor {
@Override
public void visit(Node1 node) {
// TODO Auto-generated method stub
System.err.println("Node1"+1000);
}
@Override
public void visit(Node2 node) {
// TODO Auto-generated method stub
System.err.println("Node2"+1000);
}
}
这样你就会发现,使用模式可以这么遍历,代码维护也很直观,易于理解。
优点:访问者模式对于新增的操作变得容易,访问者将有关行为集中到一个访问者对象中,而不是分散到各个节点中。
缺点:增加新的节点变的困难,每增加一个新的节点都要在访问者增加代码逻辑