public void messyPrintCollection(Collection collection) { Iterator iterator = collection.iterator() while (iterator.hasNext()) { Object o = iterator.next(); if (o instanceof Collection) messyPrintCollection((Collection)o); else System.out.println(o.toString()); } }
public void messyPrintCollection(Collection collection) { Iterator iterator = collection.iterator() while (iterator.hasNext()) { Object o = iterator.next(); if (o instanceof Collection) messyPrintCollection((Collection)o); else if (o instanceof String) System.out.println("""+o.toString()+"""); else if (o instanceof Float) System.out.println(o.toString()+"f"); else System.out.println(o.toString()); } }
public interface Visitor { public void visitCollection(Collection collection); public void visitString(String string); public void visitFloat(Float float); }
public interface Visitable { public void accept(Visitor visitor); }
对于具体的String,可能是这样:
public class VisitableString implements Visitable { private String value; public VisitableString(String string) { value = string; } public void accept(Visitor visitor) { visitor.visitString(this); } }
在accept方法中,对this类型调用正确的visitor方法:
visitor.visitString(this)
这样,就可以如下实现具体的Visitor:
public class PrintVisitor implements Visitor { public void visitCollection(Collection collection) { Iterator iterator = collection.iterator() while (iterator.hasNext()) { Object o = iterator.next(); if (o instanceof Visitable) ((Visitable)o).accept(this); }
public void visitString(String string) { System.out.println("""+string+"""); }
public void visitFloat(Float float) { System.out.println(float.toString()+"f"); } }
public class PrintVisitor implements ReflectiveVisitor { public void visitCollection(Collection collection) { ... same as above ... } public void visitString(String string) { ... same as above ... } public void visitFloat(Float float) { ... same as above ... }
public void default(Object o) { System.out.println(o.toString()); }
public void visit(Object o) { // Class.getName() returns package information as well. // This strips off the package information giving us // just the class name String methodName = o.getClass().getName(); methodName = "visit"+ methodName.substring(methodName.lastIndexOf(".")+1); // Now we try to invoke the method visit try { // Get the method visitFoo(Foo foo) Method m = getClass().getMethod(methodName, new Class[] { o.getClass() }); // Try to invoke visitFoo(Foo foo) m.invoke(this, new Object[] { o }); } catch (NoSUChMethodException e) { // No method, so do the default implementation default(o); } } }
protected Method getMethod(Class c) { Class newc = c; Method m = null; // Try the superclasses while (m == null && newc != Object.class) { String method = newc.getName(); method = "visit" + method.substring(method.lastIndexOf(".") + 1); try { m = getClass().getMethod(method, new Class[] {newc}); } catch (NoSuchMethodException e) { newc = newc.getSuperclass(); } } // Try the interfaces. If necessary, you // can sort them first to define "visitable" interface wins // in case an object implements more than one. if (newc == Object.class) { Class[] interfaces = c.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { String method = interfaces[i].getName(); method = "vis