gpt4 book ai didi

php - 在 PHP 中为方法结果缓存实现装饰器模式的最佳方法

转载 作者:可可西里 更新时间:2023-11-01 13:43:01 27 4
gpt4 key购买 nike

我有一组类,它们习惯于使用相同的参数重复调用。这些方法通常运行数据库请求并构建对象数组等,因此为了消除这种重复,我构建了几个缓存方法来进行优化。这些是这样使用的:

应用缓存之前:

public function method($arg1, $arg2) {
$result = doWork();
return $result;
}

应用缓存后:

public function method($arg1, $arg2, $useCached=true) {
if ($useCached) {return $this->tryCache();}
$result = doWork();
return $this->cache($result);
}

不幸的是,我现在只剩下手动将它添加到所有方法的稍微费力的任务 - 我相信这是装饰器模式的一个用例,但我无法弄清楚如何以更简单的方式实现它在这种情况下使用 PHP。

最好的方法是什么,希望这些类中的任何所有方法自动执行此操作,或者我只需要在方法等中添加一行?

我看过覆盖返回语句等的方法,但看不到任何东西。

谢谢!

最佳答案

如果您不需要类型安全,您可以使用通用缓存装饰器:

class Cached
{
public function __construct($instance, $cacheDir = null)
{
$this->instance = $instance;
$this->cacheDir = $cacheDir === null ? sys_get_temp_dir() : $cacheDir;
}

public function defineCachingForMethod($method, $timeToLive)
{
$this->methods[$method] = $timeToLive;
}

public function __call($method, $args)
{
if ($this->hasActiveCacheForMethod($method, $args)) {
return $this->getCachedMethodCall($method, $args);
} else {
return $this->cacheAndReturnMethodCall($method, $args);
}
}

// … followed by private methods implementing the caching

然后您可以像这样将需要缓存的实例包装到这个 Decorator 中:

$cachedInstance = new Cached(new Instance);
$cachedInstance->defineCachingForMethod('foo', 3600);

显然,$cachedInstance 没有foo() 方法。这里的技巧是utilize the magic __call method to intercept all calls to inaccessible or non-existing methods并将它们委托(delegate)给装饰实例。这样我们就可以通过装饰器公开装饰实例的整个公共(public) API。

如您所见,__call 方法还包含检查是否为该方法定义了缓存的代码。如果是这样,它将返回缓存的方法调用。如果没有,它将调用实例并缓存返回。

或者,您将专用的 CacheBackend 传递给装饰器,而不是在装饰器本身中实现缓存。然后装饰器将仅作为装饰实例和后端之间的中介。

这种通用方法的缺点是您的缓存装饰器将没有装饰实例的类型。当您的消费代码需要 Instance 类型的实例时,您将收到错误。


如果您需要类型安全的装饰器,您需要使用“经典”方法:

  1. 创建装饰实例公共(public) API 的接口(interface)。您可以手动执行此操作,或者如果工作量很大,请使用我的 Interface Distiller )
  2. 将每个需要装饰实例的方法的类型提示更改为接口(interface)
  3. 让 Decorated 实例实现它。
  4. 让 Decorator 实现它并将任何方法委托(delegate)给装饰实例
  5. 修改所有需要缓存的方法
  6. 对所有要使用装饰器的类重复此操作

简而言之

class CachedInstance implements InstanceInterface
{
public function __construct($instance, $cachingBackend)
{
// assign to properties
}

public function foo()
{
// check cachingBackend whether we need to delegate call to $instance
}
}

缺点是,它需要更多的工作。您需要为每个应该使用缓存的类执行此操作。您还需要将对缓存后端的检查放入每个函数(代码重复),并将不需要缓存的任何调用委托(delegate)给装饰实例(乏味且容易出错)。

关于php - 在 PHP 中为方法结果缓存实现装饰器模式的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17485854/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com