Web程序员最常使用的数据库封装方式就是DAO,其实和马丁大爷在PoEAA中所说的表数据入口差不多:
01 class ArticleDAO
02 {
03 public function findById($id)
04 {
05 // SELECT * FROM article WHERE id = ...
06 }
07
08 public function findByTitle($title)
09 {
10 // SELECT * FROM article WHERE title LIKE ...
11 }
12 }
如上所示,是一个最简单的DAO例子,为了提高效率,很多时候需要把查询结果都缓存起来:
01 class ArticleCache
02 {
03 protected $cache;
04 protected $dao;
05
06 public function __construct($cache, $dao)
07 {
08 $this->cache = $cache;
09 $this->dao = $dao;
10 }
11
12 public function findById($id)
13 {
14 $key = 'id_' . $id;
15 if (!($result = $this->cache->get($key))) {
16 $result = $this->cache->findById($id);
17 $this->cache->set($key, $result);
18 }
19 return $result;
20 }
21
22 public function findByTitle($title)
23 {
24 $key = 'title_' . $title;
25 if (!($result = $this->cache->get($key))) {
26 $result = $this->cache->findByTitle($title);
27 $this->cache->set($key, $result);
28 }
29 return $result;
30 }
31 }
32
33 $memcache = new Memcache();
34 $memcache->connect('host', 'port');
35
36 $dao = new ArticleDAO();
37
38 $cache = new ArticleCache($memcache, $dao);
39
40 $cache->findById('id');
41 $cache->findByTitle('title');
解决问题时,面向对象编程不变的伎俩就是引入新层,上面这个缓存功能的实现亦是如此,阿基米德当年叫嚷着:给我一个支点,我可以撬动地球;面向对象的粉丝们也常有如此的豪言:加入一个新层,就可以实现任何功能。不过这里面出现了重复的坏味道,findById和findByTitle两个方法的实现代码大体上是重复的,继续重构:
01 class Cache
02 {
03 protected $cache;
04 protected $dao;
05
06 public function __construct($cache, $dao)
07 {
08 $this->cache = $cache;
09 $this->dao = $dao;
10 }
11
12 public function __call($name, $arguments)
13 {
14 if (strtolower(substr($name, 0, 4)) != 'find') {
15 return false;
16 }
17
18 $key = md5(strtolower(get_class($this->dao) . $name . serialize($arguments)));
19 if (!($result = $this->cache->get($key, $flags))) {
20 $result = call_user_func_array(array($this->dao, $name), $arguments);
21 $this->cache->set($key, $result);
22 }
23 return $result;
24 }
25 }
26
27 $memcache = new Memcache();
28 $memcache->connect('host', 'port');
29
30 $dao = new ArticleDAO();
31
32 $cache = new Cache($memcache, $dao);
33
34 $cache->findById('id');
35 $cache->findByTitle('title');
通过使用魔术方法__call,我们成功的去除了重复代码,而且这个Cache可以说是“万能”的,因为除了ArticleDAO外,我们可能还有CategoryDAO,CommentDAO等等,都可以用这个Cache来实现缓存。当然,Cache本身还不完善,有很多提升的余地,比如说缓存时间的设置,或者内容更新时如何通过观察者模式的方式来完成缓存的主动更新等等,这些问题我就不得瑟了,留给读者自己思考。
分享到:
相关推荐
实验五: 虚拟Cache与伪相联Cache 及实验过程。
等待事件row cache lock,latch row cache objects处理过程
Maven坐标:javax.cache:cache-api:1.1.1; 标签:javax、cache、api、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和...
计算机组成原理:4.4CACHE.ppt
File::Cache 是一个 perl 模块,它允许通过文件系统跨进程共享对象数据。 现在不鼓励使用 File::Cache,而是支持 http://sourceforge.net/projects/perl-cache/ 上的新 Cache::Cache 项目。
Zend Cache:一个实用的缓存php类库
第5关:直接相联cache设计.txt
Maven坐标:org.apache.shiro:shiro-cache:1.4.0; 标签:apache、shiro、cache、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...
Maven坐标:javax.cache:cache-api:1.1.1; 标签:javax、cache、api、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码...
Android Cache Manager 是一个 android 库,可帮助使用文件缓存 JSONObjects 和 JSONArrays。 如何将库项目添加到您的项目: - 在包资源管理器中,右键单击依赖项目并选择属性。 - 在“属性”窗口中,选择左侧的...
本教程主要介绍用于Joomla!平台的一些缓存技巧。主要涉及两个组件:JRE Cache 和 PageCache 。
如果访问量大的话会给数据库造成很大的负担,所以对于变化不经常的内容要做好php 数据cache(缓存)是十分必要的。 对于一般的变量,把该变量变成php语言的格式,写到文件中,用时只要include这个文件就相当于加载了...
JetCache是Java缓存抽象,可为各种缓存解决方案提供一致的用法。 它提供的注释比Spring Cache中的注释更强大。 JetCache中的注释支持本地TTL,两级缓存和分布式自动刷新,您也可以手动编写Cache实例。 当前有四...
var gModuleConfig={outLink:{cache:true,request:false,text:"外部链接",tag:0},welcome:{cache:true,request:true,text:"今日",tag:0},read:{cache:true,request:true,text:"读信",tag:0,ajaxApi:"mbox:read...
varnish-cache:Varnish Cache源代码存储库
Laravel开发-laravel-image-cache 想象中的Laravel图像缓存
cachecloud-docker:将cachecloud打包为dockerdocker
如果访问量大的话会给数据库造成很大的负担,所以对于变化不经常的内容要做好php 数据cache(缓存)是十分必要的。 对于一般的变量,把该变量变成php语言的格式,写到文件中,用时只要include这个文件就相当于...
第一:cleanCache.sh脚本,用于定时清理后台cache内存。第二:cleanCache.sh脚本,用于定时清理后台cache内存。第三:cleanCache.sh脚本,用于定时清理后台cache内存
CacheDB