【问题标题】:Is there a significant difference between closures and the visitor pattern?闭包和访问者模式之间是否存在显着差异?
【发布时间】:2012-04-11 17:30:26
【问题描述】:

我最近一直在玩 Groovy,之前也玩过 JRuby,很欣赏在他们的集合中使用 .each{} 闭包。

也就是说,我不禁觉得这不过是访问者模式的语法糖。如果您将代码封装在一个类中的闭包主体中,并使用访问者模式传递该类的一个实例,这似乎是完全相同的事情,尽管麻烦更少。

那么,是否还有其他我还没有看到的闭包功能使它们与访问者模式有根本的不同,或者人们真的对这种语法糖感到兴奋吗?

在我看来,这更像是一个库问题而不是语言问题。


这是一个 Java 列表的快速模型,其行为似乎类似于 Groovy 列表中的 each 闭包。

public class ClosureList<E> extends ArrayList<E>{

    interface Visitor<E>{
            void visit( E e );
    }

    void accept( Visitor<E> v ){
        for( Iterator<E> myItr = this.iterator(); myItr.hasNext() )
            v.visit( myItr.next() );
    }

}

那就有

public class ClosureTest{
    public static void main( String[] args ){
        ClosureList<String> myList = new ClosureList<String>();
        myList.add( "green eggs" );
        myList.add( "green ham"  );


        clStr.accept(
                new Visitor<String>(){
                    void visit( String s ){
                        System.out.println( s )
                    }
                }
            );
    }
}

这在 Groovy 中看起来是一样的:

def l = [ "green eggs", "green ham" ]
l.each{ println it }

【问题讨论】:

  • 您能提供任何语言的代码示例吗?访问者用于避免向下转换和instanceof - 闭包(实际上,您可能是指代码块和高阶函数)如何帮助解决这个问题?
  • @TomaszNurkiewicz 好了,访问者模式似乎几乎像 Groovy 一样简洁地模拟了闭包。
  • 恕我直言,最大的区别是闭包更简洁。还有其他一些使关闭更自然的怪癖。
  • 你不是说 groovy 中的each 就像是访问者模式的简洁实现吗?除了each,还有更多的闭包
  • @PeterLawrey 大部分 bloadt 都来自这样一个事实,即没有用于 arraylist 的可变参数构造函数,然后是 2 行用于定义内部类及其方法的额外行。

标签: java oop design-patterns groovy closures


【解决方案1】:

如果您的意思是说每个函数都是访问者模式的实现,那么您是对的。不是传递接口的匿名实现,而是传递闭包。

闭包不是访客。在这种情况下,闭包用于实现访问者。

当然,在底层,闭包是通过内部类实现的,所以如果你的意思是说闭包没有什么神奇之处,我们大多数人都会同意。

关于 Java 中的闭包和匿名类之间的区别,有一些重要的范围界定点,最值得注意的是对非最终变量的访问,以及可配置的委托策略。

在 groovy 中,您还可以通过表示对实例方法的一种引用来实例化闭包,如下所示:

def c=this.&doSomething

这将创建一个 MethodClosure,您可以使用它来传输您的方法,并减少从类到方法的模块化粒度。

所以我们开始远离访问者模式了,不是吗?

我认为最终在我的理解中,闭包是一种使方法成为一等公民并获得函数式编程的好处的 OO 方式。

【讨论】:

  • 谢谢,因为从周围的所有炒作中我得到的印象是它们是一些超高级抽象,例如可以实现一类事物的延续。
  • 实际上,它们确实改变了很多东西。他们真的改变了我的编程风格,我可以说我的代码现在更短、更模块化、更可重用。但这没什么神奇的。
  • 不准确地说'each'是访问者的实现,访问者可以对每个访问的元素子类型进行不同的处理,并且可以应用于非集合。如果您愿意,可以使用闭包模拟访问者。正如其他人所指出的那样,visitor 比“each”更重要,闭包比 visitor 和 'each' 更重要。
【解决方案2】:

缺少的关键部分是 visited 对象需要有一个accept 方法。在您上面描述的示例中,each 构造中的项目不保证具有任何方法...

each 结构更类似于循环。

我还要指出,闭包是一种作用域构造,而访问者模式是一种设计模式。所以从这个角度来看,他们绝对没有彼此有任何关系。

【讨论】:

  • I'll also point out that a closure is a scoping construct, and the Visitor Pattern is a design pattern. 是的,但似乎可以用访问者模式模拟闭包,这并不重要。
  • 这就像说你可以通过驾驶汽车来学习飞行。他们彼此没有任何关系。闭包 === 什么时候在上下文中。模式 === 我如何编写代码。
猜你喜欢
  • 1970-01-01
  • 2018-12-22
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 2016-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多