SPL(标准PHP库 - Standard PHP Library)是PHP5面向对象功能中重要的部分。原文解释是这样的“The Standard PHP Library (SPL) is a collection of interfaces and classes that are meant to solve common problems”。

SplSubject 和 SplObserver 接口

The SplSubject interface is used alongside SplObserver to implement the Observer Design Pattern.

观察者模式是一种简单的事件系统,包含了两个或更多的互相交互的类。这一模式允许某个类观察另一个类的状态,当被观察类的状态发生变化时,这个模式会得到通知。被观察的类叫subject,负责观察的类叫做Observer 。PHP 提供的 SplSubject 和 SplObserver接口可用来表达这些内容。

SplSubject {
/* 方法 */
abstract public void attach ( SplObserver $observer )
abstract public void detach ( SplObserver $observer )
abstract public void notify ( void )
}

SplObserver {
/* 方法 */
abstract public void update ( SplSubject $subject )
}

这里,splsubject类维护了一个特定状态,当这个状态发生变化时,他就会调用notify方法,所以之前使用attach注册的splobserver实例的update就会被调用。这里我们实现一个简单地观察者模式的例子

<?php
/*** Subject,that who makes news*/
class Newspaper implements \SplSubject{private $name;private $observers = array();private $content;public function __construct($name) {$this->name = $name;}//add observerpublic function attach(\SplObserver $observer) {$this->observers[] = $observer;}//remove observerpublic function detach(\SplObserver $observer) {$key = array_search($observer,$this->observers, true);if($key){unset($this->observers[$key]);}}//set breakouts newspublic function breakOutNews($content) {$this->content = $content;$this->notify();}public function getContent() {return $this->content." ({$this->name})";}//notify observers(or some of them)public function notify() {foreach ($this->observers as $value) {$value->update($this);}}
}/*** Observer,that who recieves news*/
class Reader implements SplObserver{private $name;public function __construct($name) {$this->name = $name;}public function update(\SplSubject $subject) {echo $this->name.' is reading breakout news <b>'.$subject->getContent().'</b><br>';}
}$newspaper = new Newspaper('Newyork Times');$allen = new Reader('Allen');
$jim = new Reader('Jim');
$linda = new Reader('Linda');//add reader
$newspaper->attach($allen);
$newspaper->attach($jim);
$newspaper->attach($linda);//remove reader
$newspaper->detach($linda);//set break outs
$newspaper->breakOutNews('USA break down!');//=====output======
//Allen is reading breakout news USA break down! (Newyork Times)
//Jim is reading breakout news USA break down! (Newyork Times)

上例中我们通过数组存储 observer对象,使用数组及可能会出现两个问题:

1、同一个observer可能会被加载多次,导致多次调用同一个对象的update方法。

2、detach中需要通过迭代或者搜索数组来找到要删除的observer对象,导致运行效率降低。

SplObjectStorage类

PHP5提供了SplObjectStorage类,在这里我们可以用来存储observer对象,SplObjectStoraged的实例就像一个数组,但是他所存放的对象是唯一的。SplObjectStorage还可以使用detach直接从集合中删除指定的对象而不用遍历或搜索整个集合。下面看一个SplObjectStorage的例子:

<?php$ObjectStorage = new SplObjectStorage();class classa{#code...}class classb{#code...}$a = new classa();
$b = new classb();$ObjectStorage->attach($a);
$ObjectStorage->attach($b);
$ObjectStorage->attach($a);foreach ($ObjectStorage as $key => $item) {echo ($key+1).'、'.(new ReflectionClass($item))->getName()."\n";
}

//output

1、classa
  2、classb
  [Finished in 0.1s]

?>

上例中我们可以看到,在ObjectStorage这个集合中只有1个calssa,尽管我们添加了两次。并且冲集合中删除一个元素也变得极为简单,拿上面的代码来说,只需使用$ObjectStorage->attach($a);即可轻松的将$a从集合中移除。

结合 SplObjectStorage 我们再来修改最上面那个观察者模式的例子

<?php
/*** Subject,that who makes news*/
class Newspaper implements \SplSubject{private $name;private $observers;private $content;public function __construct($name) {$this->name = $name;$this->observers = new SplObjectStorage();}//add observerpublic function attach(\SplObserver $observer) {$this->observers -> attach($observer);}//remove observerpublic function detach(\SplObserver $observer) {$this->observers -> detach($observer);}//set breakouts newspublic function breakOutNews($content) {$this->content = $content;$this->notify();}public function getContent() {return $this->content." ({$this->name})";}//notify observers(or some of them)public function notify() {foreach ($this->observers as $value) {$value->update($this);}}
}/*** Observer,that who recieves news*/
class Reader implements SplObserver{private $name;public function __construct($name) {$this->name = $name;}public function update(\SplSubject $subject) {echo $this->name.' is reading breakout news '.$subject->getContent()."\n";}
}$newspaper = new Newspaper('Newyork Times');$allen = new Reader('Allen');
$jim = new Reader('Jim');
$linda = new Reader('Linda');//add reader
$newspaper->attach($allen);
$newspaper->attach($jim);
$newspaper->attach($linda);//remove reader
$newspaper->detach($linda);//set break outs
$newspaper->breakOutNews('USA break down!');//=====output======
//Allen is reading breakout news USA break down! (Newyork Times)
//Jim is reading breakout news USA break down! (Newyork Times)

转载于:https://www.cnblogs.com/kelsen/p/3791761.html

PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式相关推荐

  1. UNIX 环境高级编程总结——第五章 标准I/O 库

    5.1 流和 FILE 对象 对于标准 I/O 库,它们的操作则是围绕流(stream)进行的. 当打开一个流时,标准 I/O 函数 fopen 返回一个指向 FILE 对象的指针. 为了引用一个流, ...

  2. 一、C++面向对象高级编程(上) (侯捷)

    侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! ! 一.C++ 面向对象高级开发 1.C++面向对象高级编程(上) 2.C++面向对象高级编程(下) 二.STL 标准库和泛型编程 1.分配器 ...

  3. 一、C++面向对象高级编程(下) (侯捷)

    侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! ! 一.C++ 面向对象高级开发 1.C++面向对象高级编程(上) 2.C++面向对象高级编程(下) 二.STL 标准库和泛型编程 1.分配器 ...

  4. UNIX环境高级编程(第三版 源码及编译好的静态库文件)

    UNIX环境高级编程(第三版) 源码 及 库文件 链接: https://pan.baidu.com/s/1tPY17lWNDEbzkOwZaRUUNg 提取码: 1024 复制这段内容后打开百度网盘 ...

  5. 《UNIX 环境高级编程》学习笔记—— 标准I/O库

    UNIX环境高级编程--标准I/O库 流和 FILE 对象 标准输入.标准输出和标准错误 缓冲 打开流 读和写流 每次一行 I/O 二进制 I/O 定位流 格式化 I/O 临时文件 内存流 流和 FI ...

  6. 《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第2章 标准IO)

    2.1 Linux I/O概述 2.1.1文件I/O和标准I/O的概念 文件I/O:文件I/O称之为不带缓存的IO(unbuffered I/O).不带缓存指的是每个read,write都调用内核中的 ...

  7. 《Unix环境高级编程》---标准IO

    一.基础结构 1.文件 FILE FILE是标准IO用来表示文件的结构体,所有标准IO都以FILE为基础. stdin FILE类型的指针,指向标准输入流. stdout FILE类型的指针,指向标准 ...

  8. 标准IO库--unix环境高级编程读书笔记

    标准IO库是C语言提供的一个库,不光存在于linux中,在windows中也是有的.标准IO库和文件IO的不同是,标准IO库是对文件IO(即系统调用)的封装,并且在用户层添加了一些缓冲区. 文件IO的 ...

  9. 《UNIX环境高级编程》笔记 第五章-标准IO库

    1. 流和FILE对象 在第三章的系统调用都是围绕文件描述符fd的.但是标准I/O库函数操作则是围绕流进行的.当使用标准I/O库打开或创建一个文件时,使用一个流与一个文件关联. 当打开一个流时,标准I ...

最新文章

  1. ADPRL - 近似动态规划和强化学习 - Note 8 - 近似策略迭代 (Approximate Policy Iteration)
  2. python结束不退出_Python 基本功: 1. Hello world
  3. python os 检查同名_2020Python 爬虫面试题,高薪就业Python面试必看
  4. Linux Unix C 中的curses库——curses.h
  5. python编程学习笔记列表_python编程:从入门到实践学习笔记-函数
  6. JavaSE(十九)——equals() 和 == 的区别
  7. springboot集成rocketmq消费者
  8. easyui combobox默认选中项
  9. 参数整定临界比例度实验_PID理解起来很难?系统讲解PID控制及参数调节,理论加实际才好!...
  10. mysql中有sa_SA工作-mysql设计规范
  11. Android 系统(248)---解读Android进程优先级ADJ算法
  12. jave导出mysql_java导出mysql数据到excel(poi)
  13. SELinux 初探
  14. Android 手机 黑域
  15. 元宇宙的时代来不及解释了快上车
  16. 时序数据获取 | Python实现时间序列数据集获取
  17. 成功解决We recommend that if you want Anaconda registered as your system Python, you unregister this Pyt
  18. 常用颜色表以及中国传统颜色名录(附宏定义)
  19. 安全牛:安全与业务不存在平衡 证明价值是关键
  20. [译]OOSE第7章:Analysis 分析 7.3 The analysis model 分析模型 7.4 Summary

热门文章

  1. Android Ormlite 学习笔记1 -- 基础
  2. MVC中使用 事物
  3. Silverlight的跨站策略和跨站策略文件
  4. 3D空间的指定起点和终点的抛体运动
  5. Eclipse上安装springsource-tool-suite
  6. Oracle Q-quote delimiter Quote(q) 字符串原样输出
  7. Python 发送邮件 和 发送带附件邮件
  8. Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?
  9. android 解决password过时
  10. ios command