PHP设计模式-装饰模式实现非侵入式缓存
来源:互联网 发布:js函数not defined 编辑:程序博客网 时间:2024/06/14 00:08
本文的目标
- 简单几步,轻松实现非侵入式缓存。
本文的涉及名词
- 装饰模式 (也叫修饰模式,只是翻译不同)
- 非侵入式
- 依赖注入
名词解释
装饰模式
装饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。[修饰模式](https://zh.wikipedia.org/wiki/%E4%BF%AE%E9%A5%B0%E6%A8%A1%E5%BC%8F)
非侵入式
简单的说就是新加功能或者代码改原有代码
依赖注入
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。[控制反转](https://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC)
具体实现
常见的缓存代码:
<?php class UserModel extends BaseModel{ public function getList($id) { $key = $this->getCacheKey($id); $ret = Cache::get($key); if (empty($ret)) { $ret = $this->getFromDb($id); Cache::put($key, $ret, 1000); } return $ret; } public function getCacheKey($id) { ...... } public function geFromDb($id) { ...... }}
这样的代码带来的问题是缓存系统和数据代码高度耦合,如果需要更换或者撤销缓存系统,代码很难修改,也不好预测风险。接下来我们通过简单的几步来实现非侵入式缓存系统。
第一步先抽象出接口
<?php interface UserModelInterface { public function getList($id);}
第二步UserModel实现 UserModelInterface
<?phpclass UserModel extends BaseModel implements UserModelInterface{ public function getList($id) { return $this->getFromDb($id); } ......}
第三步使用装饰模式建立UserModelCache
<?phpclass UserModelCache extends BaseModelCache implements UserModelInterface{ public function __construct(UserModel $model) { parent::__construct($model); } public function getList($id) { return $this->cache(__METHOD__, $id, 10000); } /** * 需要缓存的数据都可以通过 * 这个类里来实现,可以通过 UserModelInterface 约束都需要实现的方法 * 如果不需要缓存的方法,会通过 BaseModelCache 的 __call 方法拦截, * 并且穿透到 UserModel 的类里面去调用。 * * 一个不需要cache的方法调用过程: * 例如调用 UserModelCache->getAll()方法,因为 UserModelCache 没有该方法, * 所以会寻找父类 BaseModelCache ,父类 * 也没有该方法,会被 BaseModelCache 的 __call 拦截,最后走到 UserModel->getAll() * 这样,只要在UserModel 实现这个 getAll 就可以了。 * * 需要cache的方法调用: * 调用 getList 会走到父类的 cache 方法,cache 方法根据传递参数生成了 cahce id, 通过 * Cache 获取数据,获取不到数据,还会走 UserModel -> getList 方法,这样就实现了缓存功能, * 而在 UserModel 里面没有嵌入任何代码。 * * 关于如果灵活实用 cahce 的问题,稍后会介绍。 */}class BaseModelCache{ protected $model = null; public function __construct(BaseModel $model) { $this->model = $model; } public function __call($method, $params) { // 通过 __call 方法来穿透 UserModelCache 不需要缓存或者未实现的方法,让 __call 去调用 // UserModel 的方法 return call_user_func_array([$this->model, $method], $params); } protected function cache($method, $params, $expire) { $key = $this->getCacheKey($method, $params); $ret = Cache::get($key); if (!$ret || CACHE_OPEN !== true) { $ret = call_user_func_array([$this->model, $method], $params); Cache::put($key, $ret, $expire); } return $ret; } protected function getCacheKey($method, $params) { return $key .... }}
第四步灵活使用
<?php // 如果没有使用框架提供的依赖注入机制,那么就要自己手动完成了。// 例如调用 UserModel 的 getList 方法class UserController { function index(UserModelInterface $user) { $user = new UserModelCache(); // 直接走 UserModel // $user = new UserModel(); // return $user->getList(); }}// 现在的很多框架都提供了依赖注入的功能,这些功能用起来更方便强大,可以让用户通过简单的配置// 来实现注入的内容,下面用 lumen 和 yii2 做两个简单的说明
第五部 lumen 和 yii2 依赖注入
通过 lumen 的 ServiceProvider 来提供依赖注入
// // 具体的路径和名称空间根据自己的实际情况来// $app->when('App\Http\Controllers\UserController')->needs('App\Models\UserModelInterface')->give('App\Models\Cache\UserModelCache');//->give('App\Models\Cache\UserModel'); 不需要缓存// 在 controller 里面直接就被注入了 UserModelCache// 如果需要其他的缓存,只需要修改此处的 give 就行了,这样就实现了// 灵活配置,不需要对底层的代码进行修改// class UserController{ function index(UserModelInterface $user) { $user->getList(); }}
yii2 是通过 ServiceLoader 和 DI 容器来实现的,涉及 Container 相关的类,具体可以参考 yii2 的文档
$container = new yii\di\Container();$container->set('UserModelInterface', 'UserModelCache');// 使用$user = $container->get('UserModelInterface');
以上代都是为了演示,并不是真实使用环境,和真实环境有差异,请自行调整
原文发在 rust.love 上。
END.
0 0
- PHP设计模式-装饰模式实现非侵入式缓存
- 用闭包实现非侵入式缓存
- PHP设计模式:装饰模式
- PHP实现装饰模式
- PHP设计模式中之装饰模式
- PHP设计模式之装饰模式
- Php设计模式之装饰者模式
- 设计模式php实例:装饰者模式
- PHP设计模式-装饰器模式
- PHP设计模式-装饰器模式
- PHP设计模式之装饰者模式
- php 设计模式 之 装饰模式
- php 设计模式 之 装饰模式
- php设计模式之装饰器模式
- PHP设计模式之装饰模式
- 【设计模式】之装饰器模式-PHP
- php设计模式之装饰模式
- PHP设计模式之装饰器模式
- 《海量小文件》分布式文件系统-TFS
- 1/29
- JQuery onload、ready概念介绍及使用方法
- java获取系统硬件信息的第三方jar包
- c# webservice上传下载
- PHP设计模式-装饰模式实现非侵入式缓存
- 内向、不善社交的人如何建立人脉?
- iOS学习之UINavigationController详解与使用(三)ToolBar
- iOS内存循环引用
- ThreadLocal的简单理解
- mongo 3 用户名跟密码创建
- 关于方向传值那点儿四儿(一)delegate
- 内向 人脉
- 面试笔试杂项积累-leetcode 26-30