装饰器模式,也称修饰器模式。目的是给现有的对象增加或修改成新逻辑。说人话就是不改变对象的情况下,给对象的某个操作增加前置操作或者后置操作(当然也有可能改变操作的逻辑)。
举个栗子:
我们在操作数据库的时候会从数据库拉取数据,拉取数据的动作是 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 多方便,一句话的事,为啥要费老大的劲做真么多的操作呢?!其实封装的目的是代码(或者说逻辑)的重复可用,现在需要拉取用户后记录数据量,那么如果来去其他的数据后也记录呢?如果不仅仅是记录还有更多的更复杂的逻辑呢?这个时候,封装的好处就尤为明显了,只需在需要添加逻辑的位置“装饰”一下,这个世界就又那么美丽了~