【发布时间】:2009-10-08 17:38:29
【问题描述】:
我不使用这种模式,也许在某些地方它本来是合适的,我使用了其他东西。你在日常编码中使用过它吗?随意以您选择的语言提供示例,并附上您的解释。
【问题讨论】:
-
有几种叫做“回调模式”的东西;请提供一个简短的定义,以便我们知道您在说哪一个。
标签: language-agnostic design-patterns
我不使用这种模式,也许在某些地方它本来是合适的,我使用了其他东西。你在日常编码中使用过它吗?随意以您选择的语言提供示例,并附上您的解释。
【问题讨论】:
标签: language-agnostic design-patterns
回调并不是真正的“模式”——更像是一个构建块。许多gang of four design patterns 以类似回调的方式使用虚拟方法。 Justin Niessner 已经提到了Observer。
回调比 OOP 早得多(并且可能比 3GL 甚至汇编程序更早)。另一个老想法是参数块 - C 解释是一个结构,其中包含要传递给函数的相关成员,因此函数不需要巨大的参数列表。
OOP 类建立在参数块之上(并为其添加一种哲学)。类实例本身是一个通过引用其方法传递的参数块。虚拟表是一个调度处理参数块。每个虚方法在调度处理参数块中都有一个回调指针。纯虚方法在参数块中为回调指针预留空间,并承诺稍后提供实际指针。
由于类是面向对象设计模式的构建块,而参数块和回调是类的构建块 - 好吧,您可以声称所有 OOP 设计模式都是基于这些想法构建的。
我想说“参数块和回调,加上指导它们使用的样式规则,启发了面向对象”,但听起来很吸引人,我不知道这是否属实。
【讨论】:
我几乎每天都在以下场景中使用回调:
事件:当用户在控件上单击鼠标、按下键或以我需要处理的方式与 UI 交互时,我订阅了控件为事件发布的委托。然后我可以通过更新 UI、在某些情况下取消事件或采取一些特殊措施来处理它。
多线程编程:在编写 GUI 时,保持 UI 响应并向用户指示长时间运行的后台事件的进度非常重要。为此,我在一个单独的线程中启动任务,然后发布委托(.NET 世界中的事件),为我的 UI 提供通知用户正在发生的进度的机会。
Lambda 函数:在 .NET 中,lambda 函数是委托的一种形式,它允许我在稍后的时间点与另一段代码的操作进行交互。 LINQ 就是一个很好的例子。我可以创建一个小的匹配函数,然后将其提供给 LINQ 查询。稍后,当我对集合执行查询时,会调用匹配函数来确定查询是否匹配。这使我不必构建或担心查询机制。我只需要告诉查询机制去哪里找出比较是否匹配。
我敢肯定,这些例子只是表面上的。但它们是我每天如何使用回调的有用示例。
【讨论】:
.NET 平台大量使用回调来实现观察者模式。
它们还用于处理异步进程。
【讨论】:
Objective C 和 Cocoa 框架大量使用它。一个例子是NSURLConnection,当连接上发生某些事情时,它将通知给它的对象(称为它的delegate):
NSURLConnection *foo = [[NSURLConnection alloc] initWithRequest:request delegate:self];
注意delegate 的传递。请求在后台进行,然后实例将向委托(在本例中为self)发送消息,例如:
connectionDidFinishLoading:
connection:didFailWithError:
你明白了。我相信这被称为“观察者模式”。这一切都与 Cocoa 的事件循环有关(据我所知,我还在学习),并且是便宜且简单的异步编程。许多不同语言的框架都遵循这种方法。
.NET 也有类似的委托。思考事件。
【讨论】:
我在 javascript 中大量使用它来让我知道异步调用何时完成,以便处理结果。
但是,在 javascript 中,现在在 C#3 中,我将函数作为参数传递,这样处理就可以继续进行,而无需显式设置要调用的委托。
【讨论】: