解析PHP观察者模式Observer
发布:smiling 来源: PHP粉丝网 添加日期:2022-04-27 11:21:45 浏览: 评论:0
Observer,首先要有一个被观察的角色,但它是【唯一的】。虽然"表演者"只有一个但是"观众"有很多,既一群"人"围观一个"人"。既然有无数个观察者,那么我们需要知道都有哪一些"人"。所以我们需要一个“容器”来记录这些"人",一个类似于数组一样来储存所有观察者的容器。
观察者模式结构图
概念
一个"演员"(被观察者),一群"观众"(观察者),一台"摄影机"(记录容器)
【观察者模式中主要角色】
1.抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。 抽象主题提供了增加和删除观察者对象的接口。
2.抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。
3.具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
4.具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致。
【使用场景】
假设项目经理让我们写了一个登陆接口,咔咔擦擦写完了
第二天让我们加入统计登陆次数,然后在后面加代码第三天让我们判断登陆地区,又在后面加代码第四天让我们在用户登陆后推送活动,再再后面加代码第N天,这个接口已经杂乱到没人想维护了。
我们需要让项目保持高内聚低耦合,就可以用到观察者模式(非必须,看需求)
【观察者模式与其它模式】
1.【中介者模式】(Mediator):通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者。
2.【单例模式】(singleton模式):ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。
代码示例
接口示例
- // 主题接口
- 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接口 - 被观察者
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();
Tags: PHP观察者模式 Observer
- 上一篇:PHP的runkit扩展如何使用
- 下一篇:最后一页
相关文章
- ·PHP设计模式之观察者模式实例(2021-07-10)
- ·PHP设计模式之观察者模式定义与用法分析(2021-11-15)
- ·PHP观察者模式实例分析【对比JS观察者模式】(2021-11-23)
- ·php设计模式之观察者模式定义与用法经典示例(2021-12-19)
- ·php模式设计之观察者模式应用实例分析(2021-12-22)
- ·PHP 观察者模式深入理解与应用分析(2021-12-22)
- ·PHP设计模式之观察者模式入门与应用案例详解(2022-01-26)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)