博主信息
博文
18
粉丝
0
评论
0
访问量
1831
积分:0
P豆:38

解析PHP观察者模式Observer

2022年01月13日 20:59:24阅读数:103博客 /

观察者模式结构图

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

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

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{

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

让他实现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 ‘小猫叫一下’;
应用
// 实时观察 $user = new user(); $user->attach(new cat()); $user->attach(new dog()); $user->login();

版权申明:本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!

全部评论

文明上网理性发言,请遵守新闻评论服务协议

条评论
  • 在之前的文章《一文了PHP中的适配器》中我们介绍了PHP中的适配器,下面本篇文章带大家了一下PHP中的
    php实现的方法:首先创建一个PHP示例文件;然后实现向主题注册;最后对注册树进行遍历,让每个对象实现其接口提供的操作即可。
    在之前的文章《深入浅PHP中的》中我们介绍了PHP中的,下面本篇文章带大家了一下PHP中的迭代器
    行为型设计有:1、备忘录即Memento,备忘录的用意是在不破坏封装的条件下,将一个对象的状态捉住;2、Observer;3、策略即Strategy,策略使得算法在用户使用的时候能独立的改变
    对于,我们可能并不是那么耳熟闻详,它是一种事件系统,意味着这一允许某个类另一一个类的状态,当被的类状态发生改变的时候,类可以收到通知并且做出相应的动作;提供了避免组件之间紧密耦合的另一种方法
    本篇文章带大家了一下Node.js中的内置块,看看Node.js内置块运行机制,通过示例简单介绍一下EventEmitter ()。
    应用场景实例,场景描述:哈票以购票为核心业务(此不限于该业务),但围绕购票会产生不同的其他逻辑,如...
    在之前的文章《深入浅PHP中的建造》中我们介绍了PHP中的建造,下面本篇文章带大家了一下PHP设计中的备忘录
    在之前的文章《深入浅PHP中的组合》中我们介绍了PHP中的组合,下面本篇文章带大家了一下PHP设计中的中介