PHP和.Net已关闭;我一直想知道在面向对象和设计模式中使用闭包的一些例子,以及它们比纯粹的OOP编程有什么优点。作为一个澄清,这不是一个OOP与函数式编程,而是如何在OOP设计中最好地使用闭包。工厂或观察者模式如何适合封闭?例如,您可以采取哪些技巧来澄清设计并导致松散耦合。关闭OOP有什么用途?
回答
闭包对事件处理很有用。这个例子是有点做作,但我认为它传达的理念是:
class FileOpener
{
public FileOpener(OpenFileTrigger trigger)
{
trigger.FileOpenTriggered += (sender, args) => { this.Open(args.PathToFile); };
}
public void Open(string pathToFile)
{
//…
}
}
我的文件首战可以通过直接调用instance.Open(pathToFile)
打开文件,或者它可以通过一些事件触发。如果我没有匿名函数+闭包,我必须编写一个没有其他目的而不是回应这个事件的方法。
假设您想要提供一个能够创建任意数量FileOpener
实例的类,但遵循IoC原则,您不希望创建FileOpener
的类实际知道如何操作(换句话说,您他们不想new
)。相反,你想使用依赖注入。但是,您只希望此类能够生成FileOpener
实例,而不仅仅是任何实例。以下是您可以执行的操作:
class AppSetup
{
private IContainer BuildDiContainer()
{
// assume this builds a dependency injection container and registers the types you want to create
}
public void setup()
{
IContainer container = BuilDiContainer();
// create a function that uses the dependency injection container to create a `FileOpener` instance
Func<FileOpener> getFileOpener =() => { return container.Resolve<FileOpener>(); };
DependsOnFileOpener dofo = new DependsOnFileOpener(getFileOpener);
}
}
现在您已经有了需要能够创建FileOpener实例的类。你可以使用依赖注入,以使其有这种能力,同时保持松耦合
class DependsOnFileOpener()
{
public DependesOnFileOpener(Func<FileOpener> getFileOpener)
{
// this class can create FileOpener instances any time it wants, without knowing where they come from
FileOpener f = getFileOpener();
}
}
有盖可使用他们的蹦床,这是重构递归迭代到的技术的任何语言。这可以帮助你摆脱许多算法难以实现的“堆栈溢出”问题。
一个蹦床是一个函数,它可以将一个闭包“反弹”回到它的调用者。封闭捕捉“其余的工作”。
例如,在Python可以定义一个递归累加器阵列中的求和的值:
testdata = range(0, 1000)
def accum(items):
if len(items) == 0:
return 0
elif len(items) == 1:
return items[0]
else:
return items[0] + accum(items[1:])
print "will blow up:", accum(testdata)
在我的机器,这掷骰子出与堆栈溢出时物品的长度超过998
同样的功能,可以在使用闭蹦床风格来完成:
def accum2(items):
bounced = trampoline(items, 0)
while (callable(bounced)):
bounced = bounced()
return bounced
def trampoline(items, initval):
if len(items) == 0:
return initval
else:
return lambda: trampoline(items[1:], initval+items[0])
通过转换递归迭代,你不吹出来的堆栈。闭包具有捕获计算状态的特性,而不是像递归那样捕获堆栈中的状态。
巧妙的把戏!我以前从未见过这种情况。这是最常见的Python(这将解释为什么我从来没有见过这种)? – FrustratedWithFormsDesigner 2010-09-30 18:48:35
这在Lisp世界很常见。在大多数Lisp实现中,它实际上是由编译器自动完成的(“tail-call optimization”)。但是有时你必须手工完成,因为编译器只能识别特定配置中的模式。 – 2010-09-30 18:56:01
我不会*在命令式语言中常见,但例如LEPL(http://www.acooke.org/lepl/)使用trampolining来防止复杂的递归下降解析器溢出堆栈。 – delnan 2010-10-01 09:47:28
- 1. 有什么用途:belongs_to关联的条件是什么?
- 2. Joomla有什么用途?
- 3. Log4j API有什么用途?
- 4. ons.ready()有什么用途?
- 5. -m开关的用途是什么?
- 6. 为什么要使用OOP概念? OOP的用法是什么?
- 7. HyerLinkField中使用HeaderText有什么用途
- 8. 直接关闭Input/OutputStream和关闭Socket有什么区别?
- 9. If-Unmodified-Since HTTP Header有什么用途?
- 10. 键值数据库有什么用途?
- 11. ruby的Hash.replace或Array.replace有什么用途?
- 12. 在oracle中有什么用途?
- 13. .DDF文件有什么用途?
- 14. makeEmptyFunction在fbjs中有什么用途?
- 15. 阿卡执行者有什么用途?
- 16. “for”属性的HTML5有什么用途?
- 17. python后端有什么用途?
- 18. 此代码更改有什么用途?
- 19. 计数有什么用途?第7行
- 20. 交叉加入有什么用途?
- 21. JavaScript中的x ++有什么用途?
- 22. Path =在XAML中有什么用途?
- 23. Java中的ByteBuffer有什么用途?
- 24. java中的hypen( - )有什么用途
- 25. 关闭有什么特别之处?
- 26. 为什么没有关闭Z
- 27. 为什么windows窗体没有关闭
- 28. Winform没有关闭为什么?
- 29. jquery ui有什么用途?为什么不使用jquery呢?
- 30. 问题有关OOP
这应该可能是社区wiki。 – notJim 2010-09-30 17:18:32
我想知道同样的事情。这个页面:http://php.net/manual/en/functions.anonymous.php有一个例子,但是它可以很容易地被重写而不用关闭。 – Galen 2010-09-30 17:24:49