当前位置:首页 > PHP教程 > php高级应用 > 列表

解析PHP观察者模式Observer

发布:smiling 来源: PHP粉丝网  添加日期:2022-04-27 11:21:45 浏览: 评论:0 

Observer,首先要有一个被观察的角色,但它是【唯一的】。虽然"表演者"只有一个但是"观众"有很多,既一群"人"围观一个"人"。既然有无数个观察者,那么我们需要知道都有哪一些"人"。所以我们需要一个“容器”来记录这些"人",一个类似于数组一样来储存所有观察者的容器。

观察者模式结构图

解析PHP观察者模式Observer

概念

一个"演员"(被观察者),一群"观众"(观察者),一台"摄影机"(记录容器)

【观察者模式中主要角色】

1.抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。 抽象主题提供了增加和删除观察者对象的接口。

2.抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。

3.具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。

4.具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致。

【使用场景】

假设项目经理让我们写了一个登陆接口,咔咔擦擦写完了

第二天让我们加入统计登陆次数,然后在后面加代码第三天让我们判断登陆地区,又在后面加代码第四天让我们在用户登陆后推送活动,再再后面加代码第N天,这个接口已经杂乱到没人想维护了。

我们需要让项目保持高内聚低耦合,就可以用到观察者模式(非必须,看需求)

【观察者模式与其它模式】

1.【中介者模式】(Mediator):通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者。

2.【单例模式】(singleton模式):ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。

代码示例

接口示例

  1. // 主题接口 
  2. interface Subject{ 
  3.     public function register(Observer $observer); 
  4.     public function notify(); 
  5. // 观察者接口 
  6. interface Observer{ 
  7.     public function watch(); 

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

被观察者

  1. // 被观察者 
  2. class Action implements Subject{ 
  3.      public $_observers=array(); 
  4.      public function register(Observer $observer){ 
  5.          $this->_observers[]=$observer
  6.      } 
  7.    
  8.      public function notify(){ 
  9.          foreach ($this->_observers as $observer) { 
  10.              $observer->watch(); 
  11.          } 
  12.    
  13.      } 
  14.  } 

Action实现了被观察者接口,他现在就是被观察者,再定义一个$_observers数组,他就是记录观众的容器了。

首先实现register方法,用它传入一个观察者,然后塞到数组里,再实现notify()方法,它会遍历容器数组,执行每个观察者的watch()方法。

观察者

  1. // 观察者 
  2. class Cat implements Observer{ 
  3.      public function watch(){ 
  4.          echo "Cat watches TV<hr/>"
  5.      } 
  6.  } 
  7.  class Dog implements Observer{ 
  8.      public function watch(){ 
  9.          echo "Dog watches TV<hr/>"
  10.      } 
  11.  } 
  12.  class People implements Observer{ 
  13.      public function watch(){ 
  14.          echo "People watches TV<hr/>"
  15.      } 
  16.  } 

这里定义了三个观察者,全都实现了Observer接口,前面的Subject会循环调用每个观察者的watch()方法,所以我们需要实现每个观察者的watch()方法。

调用:

  1. // 应用实例 
  2. $action=new Action(); 
  3. $action->register(new Cat()); 
  4. $action->register(new People()); 
  5. $action->register(new Dog()); 
  6. $action->notify(); 

首先new被观察者对象,执行它的register()方法,把每个观察者都放入容器数组,最后执行notify()方法,通知所有观察者执行自己的方法。

PHP原生自带的观察者模式

PHP有自带的观察者模式

splsubject接口 - 被观察者

Observer接口 - 观察者

SplObjectStorage对象 - 容器

首先我们有一个用户登录类

  1. class user{ 
  2.  
  3.   public function login() 
  4.   { 
  5.       echo '登录完毕' 
  6.   } 

让他实现splsubject接口成为被观察者。

首先在构造函数里,让他new SplObjectStorag()对象并赋值到属性上方便后面调用

实现attach()方法,用来注册观察者

实现detach()方法,用来删除观察者

实现notify()方法,用来遍历容器,调用每个观察者的update方法(必须是update)

rewind方法是容器指针重置到最开始,valid方法检测容器是否遍历完成并返回布尔,current方法是获取当前的观察者,next方法是将指针后移一位

修改login()方法,在里面调用notify()来通知观察者事件完成了

  1. class user implements splsubject{ 
  2.  
  3.     protected $observer = null; 
  4.  
  5.     public function __construct() 
  6.     { 
  7.         $this->observer = new SplObjectStorage(); 
  8.     } 
  9.  
  10.     public function login() 
  11.     { 
  12.         $this->notify(); 
  13.         echo '登录完毕'
  14.     } 
  15.  
  16.     public function attach(SplObserver $observer
  17.     { 
  18.         $this->observer->attach($observer); 
  19.     } 
  20.  
  21.     public function detach(SplObserver $observer
  22.     { 
  23.         $this->observer->detach($observer); 
  24.     } 
  25.  
  26.     public function notify() 
  27.     { 
  28.         $this->observer->rewind(); 
  29.         while ($this->observer->valid()) 
  30.         { 
  31.             $observer = $this->observer->current(); 
  32.             $observer->update($this); 
  33.             $this->observer->next(); 
  34.         } 
  35.     } 

观察者

每个观察者实现SplObserver接口,并实现update()方法

  1. class cat implements SplObserver { 
  2.  
  3.     public function update(SplSubject $subject
  4.     { 
  5.         echo '小猫叫一下'
  6.     } 
  7. class dog implements SplObserver { 
  8.     public function update(SplSubject $subject
  9.     { 
  10.         echo '小狗吼一声'
  11.     } 

应用

  1. // 实时观察 
  2. $user = new user(); 
  3. $user->attach(new cat()); 
  4. $user->attach(new dog()); 
  5. $user->login();

Tags: PHP观察者模式 Observer

分享到: