装饰器模式,也称修饰器模式。目的是给现有的对象增加或修改成新逻辑。说人话就是不改变对象的情况下,给对象的某个操作增加前置操作或者后置操作(当然也有可能改变操作的逻辑)。
举个栗子:
我们在操作数据库的时候会从数据库拉取数据,拉取数据的动作是 loadData,那么就可以针对loadData操作进行“装饰器”的封装。
1. 实现loadData接口,接口这里的目的是所有加载数据的地方都有一个统一的规范
interface loadDataInterface{
function loadData($where);
}
2. 实现上面的接口来封装model层
//db 是数据库的封装
class user extends db implements loadDataInterface{
function loadData($where){
//$this->db->query($where)
}
}
(一般情况下,做完上面两部,就完成了第一阶段的需求,如果后续阶段,需要在拉取用户数据后要执行特定的操作,比如说拉取了多少数据,怎么办呢?继续往下。。。)
3. 做一个装饰器
//装饰器封装了前置操作,和后置操作
abstract class loadDataDecorator implements loadDataInterface{
public $handle = null;
public $where = null;
function __construct(loadDataInterface $handle){
$this->handle = $handle;
}
abstract function loadBefore();
abstract function loadAfter();
function loadData($where){
$this->where = $where
$this->loadBefore();
$this->handle->loadData($this->where);
$this->loadAfter();
}
}
4. 实现拉取数据后记录数量的操作
class loadDataAfterCount extends loadDataDecorator{
//因为装饰器一并封装了前置操作,这里留空就行
function loadBefore(){
//do nothing
}
function loadAfter(){
//$this->db->queryCount($this->where)
}
}
5. 使用装饰器
$userModel = new loadDataAfterCount(new User)
$userModel->loadData();
装饰器带来的思考:
有些同学可能注意到了,如果要实现拉取用户后记录多少数据被拉取,那么直接改 User::loadData 多方便,一句话的事,为啥要费老大的劲做真么多的操作呢?!其实封装的目的是代码(或者说逻辑)的重复可用,现在需要拉取用户后记录数据量,那么如果来去其他的数据后也记录呢?如果不仅仅是记录还有更多的更复杂的逻辑呢?这个时候,封装的好处就尤为明显了,只需在需要添加逻辑的位置“装饰”一下,这个世界就又那么美丽了~