1、简介
访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。
2、访问者模式的使用场景
访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
从定义可以看出结构对象是使用访问者模式的必备条件,而且这个结构对象必须存在遍历自身各个对象的方法,类似于Java中的Collection。
访问者模式的目的是要把处理从数据结构中分离出来,如果系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式是个不错的选择,因为访问者模式使的算法操作的增加变得容易。
相反,如果系统的数据结构不稳定,易于变化,则此系统就不适合使用访问者模式了。
3、访问者模式类图
4、访问者模式涉及的角色
4.1、抽象访问者角色:抽象类或者接口,声明访问者可以访问哪些节点,具体到程序中就是visit方法中的参数定义哪些对象是可以被访问的。
4.2、具体访问者角色:实现抽象访问者所声明的方法,它影响到访问者访问到一个类后该干什么,要做什么事情。
4.3、抽象节点角色:接口或者抽象类,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。抽象元素一般有两类方法,一部分是本身的业务逻辑,另外就是允许接收哪类访问者来访问。
4.4、具体访问者角色:实现抽象节点类所声明的accept方法,通常都是visitor.visit(this),基本上已经形成一种定式了。
4.5、结构对象角色:一个元素的容器,一般包含一个容纳多个不同类、不同接口的容器,如List、Set、Map等,在项目中一般很少抽象出这个角色。
5、源代码
5.1、抽象访问者角色
package Visitor; /** * ******************************************************** * @ClassName: Vistor * @Description: 抽象访问者 *********************************************************** */ public interface Visitor { /* * 对应于NodeA的访问操作 */ void visit(NodeA node); /* * 对应于NodeB的访问操作 */ void visit(NodeB node); }
5.2、具体访问者A
package Visitor; /** * ******************************************************** * @ClassName: VisitorA * @Description: 具体访问者A *********************************************************** */ public class VisitorA implements Visitor{ @Override public void visit(NodeA nodeA) { System.out.println(nodeA.operationA()); } @Override public void visit(NodeB nodeB) { // TODO Auto-generated method stub System.out.println(nodeB.operationB()); } }
5.3、抽象节点
package Visitor; /** * ******************************************************** * @ClassName: Node * @Description: 抽象节点 *********************************************************** */ public abstract class Node { /* * 接受操作 */ public abstract void accept(Visitor vistor); }
5.4、具体节点A
package Visitor; /** * ******************************************************** * @ClassName: NodeA * @Description: 具体节点 *********************************************************** */ public class NodeA extends Node{ @Override public void accept(Visitor vistor) { // TODO Auto-generated method stub vistor.visit(this); } /* * NodeA 特有的商业方法 */ public String operationA(){ return "operationA is Visited"; } }
5.5、具体节点B
package Visitor; /** * ******************************************************** * @ClassName: NodeB * @Description: 具体节点B *********************************************************** */ public class NodeB extends Node{ @Override public void accept(Visitor vistor) { // TODO Auto-generated method stub vistor.visit(this); } /* * NodeB 特有的商业方法 */ public String operationB(){ return "operationB is Visited"; } }
5.6、结构对象角色
package Visitor; import java.util.Enumeration; import java.util.Vector; /** * ******************************************************** * @ClassName: ObjectStructure * @Description: 结构对象角色 *********************************************************** */ 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); } }
5.7、测试客户端
package Visitor; /** * ******************************************************** * @ClassName: Client * @Description:访问者模式测试客户端 *********************************************************** */ public class Client { private static ObjectStructure aObject; private static Visitor visitor; public static void main(String[] args) { //创建一个结构对象 aObject = new ObjectStructure(); //给结构增加一个节点 aObject.add(new NodeA()); //给结构增加一个节点 aObject.add(new NodeB()); //创建一个访问者 visitor = new VisitorA(); aObject.action(visitor); } }
6、测试 运行结果如下