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 observer
public function attach(\SplObserver $observer) {
$this->observers[] = $observer;
} //remove observer
public function detach(\SplObserver $observer) { $key = array_search($observer,$this->observers, true);
if($key){
unset($this->observers[$key]);
}
} //set breakouts news
public 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+).'、'.(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 observer
public function attach(\SplObserver $observer) {
$this->observers -> attach($observer);
} //remove observer
public function detach(\SplObserver $observer) {
$this->observers -> detach($observer);
} //set breakouts news
public 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)

PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式的更多相关文章

  1. UNIX环境高级编程 第2章 UNIX标准及实现

    在过去的将近25年时间,人们为了UNIX的标准化做出了种种努力,这使得程序在不同版本的UNIX系统之间的移植相当容易. ISO C 1989年,C语言首个标准得到批准,其为C89.次年,一个带有小改动 ...

  2. (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  3. UNIX环境高级编程---标准I/O库

    前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压 ...

  4. UNIX环境高级编程笔记之标准I/O库

    一.总结 文件I/O一章讲了不带缓冲的I/O,本章讲的是带缓冲的I/O.不带缓冲针对的是内核的系统调用,而带缓冲针对的是用户空间的标准库函数,是基于带缓冲的I/O实现的.不带缓冲的I/O通过文件描述符 ...

  5. 高级UNIX环境编程5 标准IO库

    标准IO库都围绕流进进行的 <stdio.h><wchar.h> memccpy 一般用汇编写的 ftell/fseek/ftello/fseeko/fgetpos/fsetp ...

  6. 读《C#高级编程》第1章问题

    读<C#高级编程>第1章 .Net机构体系笔记 网红的话:爸爸说我将来会是一个牛逼的程序员,因为我有一个梦,虽然脑壳笨但是做事情很能坚持. 本章主要是了解.Net的结构,都是一些概念,并没 ...

  7. (十三) [终篇] 一起学 Unix 环境高级编程 (APUE) 之 网络 IPC:套接字

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  8. unix环境高级编程基础知识之第二篇(3)

    看了unix环境高级编程第三章,把代码也都自己敲了一遍,另主要讲解了一些IO函数,read/write/fseek/fcntl:这里主要是c函数,比较容易,看多了就熟悉了.对fcntl函数讲解比较到位 ...

  9. (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

随机推荐

  1. Fis3的前端工程化之路[三大特性篇之内容嵌入]

    Fis3版本:v3.4.22 Fis3的三大特性 资源定位:获取任何开发中所使用资源的线上路径 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中 依赖声明:在一个文本文 ...

  2. 通往全栈工程师的捷径 —— react

    腾讯Bugly特约作者: 左明 首先,我们来看看 React 在世界范围的热度趋势,下图是关键词“房价”和 “React” 在 Google Trends 上的搜索量对比,蓝色的是 React,红色的 ...

  3. 解决 Springboot Unable to build Hibernate SessionFactory @Column命名不起作用

    问题: Springboot启动报错: Caused by: org.springframework.beans.factory.BeanCreationException: Error creati ...

  4. iOS开源项目周报0105

    由OpenDigg 出品的iOS开源项目周报第四期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开发方面的开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等. He ...

  5. ASP.NET Core应用针对静态文件请求的处理[3]: StaticFileMiddleware中间件如何处理针对文件请求

    我们通过<以Web的形式发布静态文件>和<条件请求与区间请求>中的实例演示,以及上面针对条件请求和区间请求的介绍,从提供的功能和特性的角度对这个名为StaticFileMidd ...

  6. Asp.net Core 初探(发布和部署Linux)

    前言 俗话说三天不学习,赶不上刘少奇.Asp.net Core更新这么长时间一直观望,周末帝都小雨,宅在家看了下Core Web App,顺便搭建了个HelloWorld环境来尝尝鲜,第一次看到.Ne ...

  7. linux拷贝命令,移动命令

    http://blog.sina.com.cn/s/blog_7479f7990101089d.html

  8. css_02之盒模型、渐变

    1.框模型:盒模型,①对象实际宽度=左右外边距+左右边框+左右内边距 + width:②对象实际高度=上下外边距+上下边框+上下内边距 + height: 2.外边距:margin:取值:①top(上 ...

  9. Oracle 10g安装教程

    首先下载安装文件,打开后文件结构如图所示: 安装之前请关闭Windows防火墙并断开网络. xp系统下直接双击运行(本经验以XP系统安装为例进行讲述). 如果是在win7上安装,如图:在setup文件 ...

  10. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...