鉴于一个类有一些非常昂贵的代码,我想避免在重新定义实例时运行该代码。
最好用一些伪代码解释:
$foo = new Foo('bar');
print $foo->eat_cpu_and_database_resources(); #=> 3.14159
$foo->store_in_cache(); #Uses an existing Memcached and/or caching to store serialized.
#new thread, such as a new HTTP request. Could be days later.
$bar = new Foo('bar');
print $foo->eat_cpu_and_database_resources(); #=> 3.14159
第二个$ bar应该重新初始化先前创建的实例$ foo。在我的实际课程中,我在eat_cpu_and_database_resources()
上做了几件事,名为get_weighted_tags()
:根据$foo->tags
中的值计算加权的tagcloud。 $foo->tags()
充满了昂贵的$foo->add_tag()
电话。我想从现在开始从缓存中检索准备好并填充的实例。
我试图简单地从__construct()上的(序列化)缓存中获取并将检索到的实例分配给$this
,这在PHP中是不允许的:
function __construct ($id) {
if ($cached = $this->cache_get($id)) {
$this = $cached
}
else {
#initialize normally
}
}
这是正确的方法吗?或者我应该将每个实例都视为唯一,而是在eat_cpu_and_database_resources()
方法中应用缓存,而不是缓存整个实例?
PHP中是否有内置的方法来恢复旧实例(在新线程中)?
答案 0 :(得分:2)
根据Foo的大小,您可能希望将整个对象缓存在Drupal提供的缓存存储中。如果它太大了,看看将结果缓存到昂贵的方法调用是否有意义。
如果要从PHP内部格式反序列化对象,则必须使用相应的unserialize
方法,并且可能需要添加magic __wakeup
method以进行任何重新初始化后的操作:
__wakeup
的预期用途是重新建立在序列化期间可能已丢失的任何数据库连接并执行其他重新初始化任务。
由于您必须首先使用序列化字符串,因此您可能需要添加一些便利来封装此逻辑,例如Factory或Builder模式或专用的FooCache。
我个人认为缓存方法调用是最好的选择,因为当它实际上只是方法调用很昂贵时,缓存整个对象是没有意义的。这也将为您节省任何额外的工作,检查是否有序列化字符串开始或建立工厂。