PHP设计模式之观察者模式
使用场景#
假设项目经理让我们写了一个登陆接口,咔咔擦擦写完了
- 第二天让我们加入统计登陆次数,然后在后面加代码
- 第三天让我们判断登陆地区,又在后面加代码
- 第四天让我们在用户登陆后推送活动,再再后面加代码
- 第 N 天,这个接口已经杂乱到没人想维护了
我们需要让项目保持高内聚低耦合,就可以用到观察者模式(也不是非要,看需求)
概念#
观察者,观察者,首先要有个被人观察的角色,这是唯一的,然后会有无数个观察者去看她,可以说是一群人在围观一个人,既然有无数个观众,那总得有个东西记录有哪些观察者,那就应该有一个类似于数组一样来储存所有观察者,总结就是一个被观察者,无数个观察者,再有一个容器记录
代码示例#
- 接口示例 Subject 就是被观察者,Observer 就是观众,也就是观察者
// 主题接口 interface Subject{ public function register(Observer $observer); public function notify(); } // 观察者接口 interface Observer{ public function watch(); }
被观察者#
// 被观察者
class Action implements Subject{
public $_observers=array();
public function register(Observer $observer){
$this->_observers[]=$observer;
}
public function notify(){
foreach ($this->_observers as $observer) {
$observer->watch();
}
}
}
Action 实现了被观察者接口,他现在就是被观察者,再定义一个 $_observers 数组,他就是记录观众的容器了。
首先实现 register 方法,用它传入一个观察者,然后塞到数组里,再实现 notify () 方法,它会遍历容器数组,执行每个观察者的 watch () 方法。
观察者#
// 观察者
class Cat implements Observer{
public function watch(){
echo "Cat watches TV<hr/>";
}
}
class Dog implements Observer{
public function watch(){
echo "Dog watches TV<hr/>";
}
}
class People implements Observer{
public function watch(){
echo "People watches TV<hr/>";
}
}
这里定义了三个观察者,全都实现了 Observer 接口,前面的 Subject 会循环调用每个观察者的 watch () 方法,所以我们需要实现每个观察者的 watch () 方法。
调用#
// 应用实例
$action=new Action();
$action->register(new Cat());
$action->register(new People());
$action->register(new Dog());
$action->notify();
首先 new 被观察者对象,执行它的 register () 方法,把每个观察者都放入容器数组,最后执行 notify () 方法,通知所有观察者执行自己的方法。
PHP 原生自带的观察者模式#
PHP 有自带的观察者模式
- splsubject 接口 - 被观察者
- Observer 接口 - 观察者
- SplObjectStorage 对象 - 容器
首先我们有一个用户登录类
class user{
public function login()
{
echo '登录完毕'
}
让他实现 splsubject 接口成为被观察者。
首先在构造函数里,让他 new SplObjectStorag () 对象并赋值到属性上方便后面调用
实现 attach () 方法,用来注册观察者
实现 detach () 方法,用来删除观察者
实现 notify () 方法,用来遍历容器,调用每个观察者的 update 方法 (必须是 update)
rewind 方法是容器指针重置到最开始,valid 方法检测容器是否遍历完成并返回布尔,current 方法是获取当前的观察者,next 方法是将指针后移一位
修改 login () 方法,在里面调用 notify () 来通知观察者事件完成了
class user implements splsubject{ protected $observer = null; public function __construct() { $this->observer = new SplObjectStorage(); } public function login() { $this->notify(); echo '登录完毕'; } public function attach(SplObserver $observer) { $this->observer->attach($observer); } public function detach(SplObserver $observer) { $this->observer->detach($observer); } public function notify() { $this->observer->rewind(); while ($this->observer->valid()) { $observer = $this->observer->current(); $observer->update($this); $this->observer->next(); } } }
观察者#
每个观察者实现 SplObserver 接口,并实现 update () 方法
class cat implements SplObserver {
public function update(SplSubject $subject)
{
echo '小猫叫一下';
}
}
class dog implements SplObserver {
public function update(SplSubject $subject)
{
echo '小狗吼一声';
}
}
应用#
// 实时观察
$user = new user();
$user->attach(new cat());
$user->attach(new dog());
$user->login();
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: