什么是观察者模式(PHP原生SPL)

使用场景

假设项目经理让我们写了一个登陆接口,咔咔擦擦写完了
第二天让我们加入统计登陆次数,然后在后面加代码
第三天让我们判断登陆地区,又在后面加代码
第四天让我们在用户登陆后推送活动,再再后面加代码
第N天,这个接口已经杂乱到没人想维护了
我们需要让项目保持高内聚低耦合,就可以用到观察者模式(也不是非要,看需求)

概念

观察者,观察者,首先要有个被人观察的角色,这是唯一的,然后会有无数个观察者去看她,可以说是一群人在围观一个人,既然有无数个观众,那总得有个东西记录有哪些观察者,那就应该有一个类似于数组一样来储存所有观察者,总结就是一个被观察者,无数个观察者,再有一个容器记录

代码示例

接口示例
// 主题接口
interface Subject{
    public function register(Observer $observer);
    public function notify();
}
// 观察者接口
interface Observer{
    public function watch();
}

Subject就是被观察者,Observer就是观众,也就是观察者

被观察者
// 被观察者
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接口 - 被观察者
SplObserver接口 - 观察者
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();

————————————————
版权声明:本文为CSDN博主「八重樱。」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43814458/article/details/108088947

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 夜莺2517阅读 128,605评论 1赞 9
  • 版本:ios 1.2.1 亮点: 1.app角标可以实时更新天气温度或选择空气质量,建议处女座就不要选了,不然老想...
    我就是沉沉阅读 7,848评论 1赞 6
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 9,114评论 28赞 54
  • 兔子虽然是枚小硕 但学校的硕士四人寝不够 就被分到了博士楼里 两人一间 在学校的最西边 靠山 兔子的室友身体不好 ...
    待业的兔子阅读 2,912评论 2赞 9

友情链接更多精彩内容