用闭包实现非侵入式缓存
来源:互联网 发布:网络促销手段 编辑:程序博客网 时间:2024/05/19 18:37
目标 :PHP 用闭包实现非侵入式缓存
优点 :
- 非侵入式
- 依赖注入
写这个博客的原因是:
公司项目大量的使用了缓存,但是我们最开始使用的缓存代码耦合度太高,并且代码看起来比较混乱。所以我决定写一个非侵入式的缓存系统,将正常代码和缓存代码分开,降低耦合度。 但是传统的纯面向对象的实现会出现大量的类。而PHP借助于闭包特性可以用较少的类实现,并且避免了继承这种强耦合。
实现:
常见缓存代码:
$live = $redis->get('home_live_'.$page); if(!$live){ $live = $member->live($page); $redis->set('home_live_'.$page,serialize($live),10); } else{ $live = unserialize($live); }
这种方式的缺点是:缓存代码与原代码耦合太严重,一旦决定不使用缓存或者更换缓存会非常麻烦
非侵入式缓存:
1.纯面向对象实现方式:
class Cache{}interface MemberModelInterface{ public function getList();}class MemberModel implements MemberModelInterface{ public function getList() { return array('1','2','3','4','5'); }}class BaseModelCache{ const CACHE_OPEN = false; private $redis; private $model; public function __construct(UserModel $model) { $this->redis = new \Redis; $this->redis->connect('127.0.0.1',6379); $this->model = $model; } public function cache($method , $params , $expire) { $rs = $this->redis->get('list'); if(!$rs || self::CACHE_OPEN !== true){ $rss = call_user_func_array([$this->model,$method],$params); $this->redis->set('list',json_encode($rss),$expire); } return $rs; }}class MemberModelCache extends BaseModelCache implements MemberModelInterface{ public function __construct(MemberModel $model) { parent::__construct($model); } public function getList() { // TODO: Implement getList() method. return $this->cache('getList',[],100); }}$member = new MemberModelCache(new MemberModel());var_dump($member->getList());
这里没有把缓存类封装起来,所以Cache类是空的。这种实现方法每个Model都需要有一个cache类并且实现同一个接口。类数量太多的同时,由于Model类和ModelCache类需要同时实现一个接口,所以也具有较高的耦合度。
闭包实现:
<?phpclass RedisCache{ private $handler; public function __construct($options=array()) { $options = array_merge(array ( 'host' => '127.0.0.1', 'port' => 6379, 'timeout' => false, 'persistent' => false, ),$options); $this->handler = new \Redis; $this->handler->connect($options['host'], $options['port']) : } public function cache(Closure $func,$expire,$cacheName) { $rs = $this->handler->get($cacheName); if(!$rs){ $rs = $func(); $this->handler->set($cacheName,json_encode($rs),$expire); } return $rs; } public function __call($func_name,$args) { return call_user_func_array([$this->handler,$func_name],$args); }}class NonInvasiveCache{ const DEFAULT_CACHE_TYPE = 'Redis'; private $cache; public function __construct() { $this->cache = $this->connect('Redis'); } public function connect($cacheType='',$options=array()) { if(empty($cacheType)) $cacheType = self::DEFAULT_CACHE_TYPE; $class = $cacheType.'Cache'; if(class_exists($class)){ $cache = new $class($options); } else{ throw new Exception($cacheType.' Driver does not exists'); } return $cache; } public function useCache($func,$expire,$cacheName){ if(is_array($func)){ if(is_object($func[0]) && is_string($func[1]) && (empty($func[2]) || is_array($func[2]) )){ $func = $this->makeClosure($func[0],$func[1],$funcp[2]); }else{ throw new Exception('First param error'); } } $funcRf = new \ReflectionFunction($func); if(!$funcRf->isClosure()){ throw new Exception('First param error,it must be a Closure or Array'); } return $this->cache->cache($func,$expire,$cacheName); } public function makeClosure(&$class,$mothod,$args=array()){ $f = function() use(&$class,&$mothod,&$args){// xdebug_debug_zval( 'class' );//查看引用计数,没有拷贝对象的操作 return call_user_func_array([$class,$mothod],$args); }; return $f; } public static function instance() { static $thisCache = false; if(!$thisCache){ $thisCache = new NonInvasiveCache(); } return $thisCache; }}class MemberModel { public function getList() { return array('1','2','3','4','5'); }}$member = new MemberModel();$cache = new NonInvasiveCache();//两种用法://第一种:第一个参数传数组,第二个参数传过期时间,第三个参数是键名$data = $cache->useCache([$user,'getList'],10,'redisCache');//第二种:第一个参数传匿名函数$data = $cache->useCache(function(){return array('1','2','3','4','5');},10,'redisCache');
使用闭包实现减少了类的数量,并且Model类不需要实现接口,降低了耦合度,还可以使用匿名函数,使用起来更加方便。
这里只封装了使用普通的字符类型做缓存的例子,简单介绍一下这个实现方法。
0 0
- 用闭包实现非侵入式缓存
- PHP设计模式-装饰模式实现非侵入式缓存
- 非侵入式
- 关于侵入式和非侵入式
- 侵入式与非侵入式概念
- Spring 侵入式和非侵入式
- 关于STL容器实现,非侵入式容器+Iterator框架和“侵入式”容器实现的思考
- 侵入式和非侵入式的区别
- 浅谈侵入式开发与非侵入式开发
- 侵入式和非侵入式的区别
- 侵入式和非侵入式的区别
- 【转】非侵入式设计 和侵入式设计 意思?
- 非侵入式设计和侵入式设计
- 侵入式和非侵入式的区别
- 侵入式和非侵入式的区别
- 侵入式和非侵入式的区别
- 侵入式和非侵入式的区别
- 侵入式和非侵入式的区别
- algorithm 1.4.18
- Maven入门基础
- 原生jsAJax实现代码
- Java设计模式---单例模式的实现
- 使用Anaconda安装Python
- 用闭包实现非侵入式缓存
- josnp跨域
- 设计模式-结构型-代理模式(Proxy)
- HDOJ 3549 Flow Problem(最大流)
- listview的item里面有Button,并给其设置了点击事件,而且有效可点击,但是listview的item点击事件却失效了
- 修改maven本地仓库路径
- FPGA学习手记(三)准备工作——和谐ModelSim10.0(已验证至10.0c)
- http协议详解
- 防范 DDoS 攻击的 15 个方法