Mar*_*ian 5 php oop caching design-patterns decorator
我有一组习惯用相同的参数重复调用的类.这些方法通常运行数据库请求并构建对象数组等,因此为了减少这种重复,我构建了一些优化的缓存方法.这些使用如下:
在应用缓存之前:
public function method($arg1, $arg2) {
$result = doWork();
return $result;
}
Run Code Online (Sandbox Code Playgroud)
应用缓存后:
public function method($arg1, $arg2, $useCached=true) {
if ($useCached) {return $this->tryCache();}
$result = doWork();
return $this->cache($result);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我现在离开了稍微费力的任务,手动将其添加到所有方法 - 我相信这是装饰器模式的用例,但我无法弄清楚如何在PHP中以更简单的方式实现它这个案例.
这样做的最好方法是什么,希望这些类中的所有方法都可以自动执行此操作,或者我只需要在方法中添加一行等等?
我已经看过了覆盖return语句的方法,但是看不到任何东西.
谢谢!
Gor*_*don 10
如果您不需要Type Safety,则可以使用通用的Cache Decorator:
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
Run Code Online (Sandbox Code Playgroud)
然后,您将需要缓存的实例包装到此Decorator中,如下所示:
$cachedInstance = new Cached(new Instance);
$cachedInstance->defineCachingForMethod('foo', 3600);
Run Code Online (Sandbox Code Playgroud)
显然,$cachedInstance没有foo()方法.这里的技巧是利用魔术__call方法拦截对不可访问或不存在的方法的所有调用,并将它们委托给装饰实例.这样我们就可以通过Decorator公开装饰实例的整个公共API.
如您所见,该__call方法还包含用于检查是否存在为该方法定义的缓存的代码.如果是这样,它将返回缓存的方法调用.如果没有,它将调用实例并缓存返回.
或者,您将专用的CacheBackend传递给Decorator,而不是在装饰器本身中实现缓存.然后,Decorator将仅作为装饰实例和后端之间的介体.
这种通用方法的缺点是您的缓存装饰器不具有装饰实例的类型.当您的消费代码需要Instance类型的实例时,您将收到错误.
如果您需要类型安全的装饰器,则需要使用"经典"方法:
简而言之
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
}
}
Run Code Online (Sandbox Code Playgroud)
的缺点是,它是更多的工作.您需要为每个应该使用缓存的类执行此操作.您还需要将检查放入缓存后端到每个函数(代码复制),以及将任何不需要缓存的调用委托给装饰实例(繁琐且容易出错).
| 归档时间: |
|
| 查看次数: |
2304 次 |
| 最近记录: |