java中的通用访客模式

cib*_*en1 0 java generics templates visitor

以下是使用泛型的访问者模式的java实现,一般是否有用?(我想是的).

它能以某种方式得到改善吗?使用匿名类轻松调用很重要.谢谢.

(使用示例):

Vector<Number> numbers = new Vector<Number>();

        numbers.add(new Double(1.2));
        numbers.add(new Float(-1.2));
        numbers.add(new Double(4.8));
        numbers.add(new Float(-3.4));
        numbers.add(new Long(123456));
        numbers.add(new Short("14"));

        For.each(numbers, new Visitor<Number>() {
            public void doIt(Double n) {
                System.out.println("doIt() for double: " + n);
            }
            public void doIt(Float n) {
                System.out.println("doIt() for float: " + n);
            }
            public void doIt(Number n) {
                System.out.println("doIt() for Number: " + n);
            }
        });

        Visitor<Number> visi =  new Visitor<Number>() {
            private StringBuffer  all = new StringBuffer ();
            public void doIt(Number n) {
                System.out.println("doIt() for Number: " + n);
                all.append(n.toString() + " ");
            }
            public Object getResult () {
                return all;
            }
        };

        For.each(numbers, visi);

        System.out.println ("all -> " + visi.getResult());
Run Code Online (Sandbox Code Playgroud)

定义:

//............................................
abstract class Visitor<T> {
    public void visit(T n) {
        try {
            this.getClass().getDeclaredMethod("doIt", n.getClass()).invoke(this, n);
        } catch (Exception ex) {
            doIt((T) n);
        }
    }
    public void doIt(T n) {
        System.out.println("doIt() for base " + n);
    }
    public Object getResult() {
        return null;
    }
} // class

//............................................
class For {
    public static <T> void each (Collection<T> c, Visitor<T> f) {
        for (T v : c) {
            f.visit(v);
        }
    } // ()
} // class
Run Code Online (Sandbox Code Playgroud)

Don*_*oby 6

这不是访客模式.

访问者的特征在于,访问者具有accept(Visitor v)与访问者中的访问方法相互作用的方法,该方法将访问者作为参数并且针对不同类型的访问者进行过载,从而形成"双重调度"机制.

引自设计模式访客的"适用性"部分:

使用访客模式时
  • 对象结构包含许多具有不同接口的对象类,并且您希望对依赖于其具体类的这些对象执行操作.
  • 需要对对象结构中的对象执行许多不同且不相关的操作,并且您希望避免使用这些操作"污染"它们的类.访问者允许您通过在一个类中定义它们来保持相关操作.当许多应用程序共享对象结构时,使用Visitor将操作放在那些需要它们的应用程序中.
  • 定义对象结构的类很少改变,但是你经常想要在结构上定义新的操作.更改对象结构类需要重新定义所有访问者的界面,这可能是昂贵的.如果对象结构类经常更改,那么在这些类中定义操作可能更好.

因此,这种模式用于处理多种类型对象上的类似操作.在您的示例中,您呼叫访问者的对象只能处理一种类型.

在你的答案中修改使用反射来处理多种类型(顺便说一句,这样做可以更好地作为对问题的编辑或作为一个单独的问题),你要避免accept(Visitor v)使用反射在被访问类中创建一个方法,这是在一定程度上实现了同一个目标,但有些尴尬.我仍然会拒绝将其称为访客的实施.

如果您在此处撰写的样式中的代码对您有用,请务必使用它,但请不要将其称为访问者.

这更像是一个策略模式或一个函数对象,如果你以反映它的方式重命名泛型类,它实际上是有用的,你的用法类似于函数式语言中列表处理的常见模式.

我可能会从问题的代码做的是重命名Visitor<T>到Operation<T>和你的命名visit(T t)到execute(T t)或apply(T t),一个思想Operation为Function没有返回值.事实上,我的确使用的方式类似于你正在做的事情,并使用类似的策略来使用通用Function<Domain, Range>对象进行集合"映射" .我不确定哪个模式名称实际适合它,但它不是访客.它为OO世界带来了功能列表理解风格,其中函数不是天生的一流对象.