【发布时间】:2013-10-27 17:09:56
【问题描述】:
我有一些对我很有效的模式,但是我很难向其他程序员解释。我正在寻找一些理由或文献参考。
我个人使用 PHP,但这也适用于 Java、Javascript、C++ 和类似语言。示例将在 PHP 或 Pseudocode 中,我希望你能忍受。
这个想法是对中间结果使用惰性求值容器,以避免对同一个中间值进行多次计算。
“动态编程”:
http://en.wikipedia.org/wiki/Dynamic_programming
动态规划方法试图只解决每个子问题一次,从而减少计算次数:一旦计算了给定子问题的解决方案,它就会被存储或“记忆化”:下一次相同的解决方案是需要的,简单查一下
惰性评估容器:
class LazyEvaluationContainer {
protected $values = array();
function get($key) {
if (isset($this->values[$key])) {
return $this->values[$key];
}
if (method_exists($this, $key)) {
return $this->values[$key] = $this->$key();
}
throw new Exception("Key $key not supported.");
}
protected function foo() {
// Make sure that bar() runs only once.
return $this->get('bar') + $this->get('bar');
}
protected function bar() {
.. // expensive computation.
}
}
使用类似的容器,例如作为依赖注入容器(DIC)。
详情
我通常使用这个的一些变体。
- 是否可以将实际数据方法与数据计算方法放在不同的对象中?
- 是否可以有带参数的计算方法,使用带有嵌套数组的缓存?
- 在 PHP 中,可以使用魔术方法(__get() 或 __call())作为主要检索方法。结合类 docblock 中的“@property”,可以为每个“虚拟”属性提供类型提示。
- 我经常使用诸如“get_someValue()”之类的方法名称,其中“someValue”是实际的键,以区别于常规方法。
- 是否可以将数据计算分配给多个对象,以获得某种关注点分离?
- 可以预初始化一些值吗?
编辑:问题
关于 Spring @Configuration 类中的一个可爱的机制,已经有一个很好的答案。
为了使这个更有用和有趣,我稍微扩展/澄清这个问题:
- 存储来自动态编程的中间值是否合法?
- 在 PHP 中实现此功能的最佳实践是什么? “细节”中的一些东西是不是又丑又丑?
【问题讨论】:
-
所以...它是一个缓存,不是吗?
-
您正在缓存结果?
-
是的,这是一种说法。当然缓存在内存级别,没有持久存储。
-
顺便说一句,我来自 Composer 的这个 PR,github.com/composer/composer/pull/2298。不过,我不希望任何不真正感兴趣的人阅读这篇文章。 (是的,我意识到 igorw 抱怨构造函数是有道理的)
标签: php dynamic-programming lazy-evaluation data-containers