设计模式在java的中型系统中应用广泛,遵循一定的编程模式,才能使自己的代码便于理解,易于交流,Visitor(访问者)模式是比较常用的一个模式. 应用场景:对于某对象结构中各元素的操作。如果需要在不修改各元素类的前提下定义作用于这些元素的新操作,也就是动态的增加新的方法应该考虑访问者模式。 想让数个不同的访问者对同一个对象集合进行访问时,Visitor模式可以发挥它的强大作用。Visitor先调用了Visitable类中的方法,这个方法又回调到Visitor类中 在此写了10个java类来描述说明Visitor设计模式; 1、 NodeA.java 可访问节点A 2、 NodeB.java 可访问节点B 3、 NodeC.java 可访问节点C 4、 Visitable.java 可访问对象接口 5、 Visitor.java 访问者接口 6、 VisitorA.java 访问者A 7、 VisitorTest.java 带有main方法的测试类 5变体、 Visitor.java 访问者接口(应用java反射机制) 6变体、 VisitorA.java 访问者A(应用java反射机制) 7变体、 VisitorTest.java 带有main方法的测试类(应用java反射机制)
=============== 1、 NodeA.javapackage visitor;public class NodeA implements Visitable { public void accept(Visitor visitor) { visitor.visit(this); }}=============== 1 end
=============== 2、 NodeB.javapackage visitor;public class NodeB implements Visitable { public void accept(Visitor visitor) { visitor.visit(this); }}=============== 2 end
=============== 3、 NodeC.javapackage visitor;public class NodeC implements Visitable { public void accept(Visitor visitor) { visitor.visit(this); }}=============== 3 end
=============== 4、 Visitable.javapackage visitor;public interface Visitable { public void accept(Visitor visitor);}=============== 4 end
=============== 5、 Visitor.javapackage visitor;import java.util.Collection;public interface Visitor { //访问节点A public void visit(NodeA nodeA); //访问节点B public void visit(NodeB nodeB); //访问节点C public void visit(NodeC nodeC); //访问节点集合 public void visitCollection(Collection collection); }=============== 5 end
=============== 6、 VisitorA.javapackage visitor;import java.util.Collection;import java.util.Iterator;public class VisitorA implements Visitor { public void visit(NodeA a){ System.out.println("Execute visitNodeA method!");; } public void visit(NodeB b){ System.out.println("Execute visitNodeB method!");; } public void visit(NodeC c){ System.out.println("Execute visitNodeC method!");; } public void visitCollection(Collection collection){ Iterator iterator = collection.iterator(); while (iterator.hasNext()) { Object o = iterator.next(); if (o instanceof Visitable) ((Visitable)o).accept(this); } }}=============== 6 end =============== 7、 VisitorTest.javapackage visitor;import java.util.ArrayList;import java.util.List;public class VisitorTest { public static void main(String[] args) { NodeA nodeA = new NodeA(); NodeB nodeB = new NodeB(); NodeC nodeC = new NodeC(); VisitorTest nodeD = new VisitorTest(); //访问单个对象 VisitorA visitorA = new VisitorA(); visitorA.visit(nodeA); visitorA.visit(nodeB); visitorA.visit(nodeC); //访问集合 List<Visitable> list = new ArrayList<Visitable>(); list.add(nodeA); list.add(nodeB); list.add(nodeC); visitorA.visitCollection(list); }}=============== 7 end
在两个接口Visitor和Visitable中,确保Visitable很少变化,也就是说,确保不能老有新的Element元素类型加进来,可以变化的是访问者行为或操作,也就是Visitor的不同子类可以有多种,这样使用访问者模式最方便. 当然采用java反射机制, 可以使对象集合中的对象经常有变化。
采用java反射机制的 Visitor 变体
采用了java反射机制的vistor变体,类1,2,3,4 均不变 通过使用Java Reflection,可以增强Visitor模式,使之具有操作对象结构的强大功能,并在增加新Visitable类型方面提供灵活性。=============== 5变体、 Visitor.javapackage visitor;public interface Visitor { //访问者触发的方法 public void visit(Object o);}=============== 5变体 end
=============== 6变体、 VisitorA.javapackage visitor;import java.lang.reflect.Method;import java.util.AbstractCollection;import java.util.Iterator;public class VisitorA implements Visitor { public void visitObject(Object o) { System.out.println("Execute visitObject method!");; } public void visitNodeA(NodeA a){ System.out.println("Execute visitNodeA method!");; } public void visitNodeB(NodeB b){ System.out.println("Execute visitNodeB method!");; } public void visitNodeC(NodeC c){ System.out.println("Execute visitNodeC method!");; } public void visitAbstractCollection(AbstractCollection<Visitable> collection){ Iterator<Visitable> iterator = collection.iterator(); while(iterator.hasNext()){ iterator.next().accept(this); } } //对o元素进行访问 public void visit(Object o){ try { //1 Get the method of visitor needed to call Method m = getMethod(o.getClass()); //2 execute the method m.invoke(this, new Object[]{o}); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } }
//根据传进来的类名获得访问者需要执行的方法 protected Method getMethod(Class c) { Class newc = c; Method m = null; //根据传进来的类名去寻找相应的方法,如果不从在就去超类中找 String method = null; while (m == null && newc != Object.class) { method = "visit" + newc.getSimpleName(); try { m = getClass().getMethod(method, new Class[] {newc}); } catch (NoSuchMethodException e) { newc = newc.getSuperclass(); } } //如果超类是Object,则到接口中找 if (newc == Object.class) { Class[] interfaces = c.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { method = "visit" + interfaces[i].getSimpleName(); try { m = getClass().getMethod(method, new Class[] {interfaces[i]}); } catch (NoSuchMethodException e) {} } } //如果m==null,则执行visitor中默认的方法 if (m == null) { try { m = this.getClass().getMethod("visitObject", new Class[] {Object.class}); } catch (Exception e) {} } return m; }
}=============== 6变体 end =============== 7变体、 VisitorTest.javapackage visitor;import java.util.ArrayList;import java.util.List;public class VisitorTest { public static void main(String[] args) { NodeA nodeA = new NodeA(); NodeB nodeB = new NodeB(); NodeC nodeC = new NodeC(); VisitorTest nodeD = new VisitorTest(); //访问单个对象 VisitorA visitorA = new VisitorA(); visitorA.visit(nodeA); visitorA.visit(nodeB); visitorA.visit(nodeC); visitorA.visit(nodeD); //访问集合 List<Visitable> list = new ArrayList<Visitable>(); list.add(nodeA); list.add(nodeB); list.add(nodeC); visitorA.visit(list); }}=============== 7变体 end