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)

最新文章

  1. agsXMPP
  2. asp.net mvc 上传文件
  3. js声明json数据,打印json数据,遍历json数据
  4. iOS WebView调用JS的一个小坑
  5. FK JavaScript之:ArcGIS JavaScript添加Graphic,地图界面却不显示
  6. C#代码像QQ的右下角消息框一样,无论现在用户的焦点在哪个窗口,消息框弹出后都不影响焦点的变化,那么有两种方法
  7. Cocos2d-x解析XML文件,解决中文乱码
  8. BZOJ_1011_[HNOI2008]_遥远的行星_(近似)
  9. ClassLoader 工作机制
  10. 使用nginx作为websocket的proxy server
  11. 23 服务IntentService Demo6
  12. 如何使用ZOL一键安装器下载中关村在线的源安装包
  13. 【C++ mid-term exerises】
  14. matlab知识
  15. Python_装饰器_29
  16. Elasticsearch 基础知识要点与性能监控
  17. 洛谷P1219 八皇后【dfs】
  18. 题解 P1130 【红牌】
  19. matlib实现logistic回归算法(序一)
  20. 【校招面试 之 C/C++】第5题 C++各种构造函数的写法

热门文章

  1. NPM (node package manager) 入门 - 基础使用
  2. Cassandra简介
  3. Ubuntu 14.04中Elasticsearch集群配置
  4. 用html5的canvas和JavaScript创建一个绘图程序
  5. Vue-Router 页面正在加载特效
  6. C#开发微信门户及应用(39)--使用微信JSSDK实现签到的功能
  7. SSH框架和Redis的整合(2)
  8. Function.prototype.toString 的使用技巧
  9. mysql删除重复记录语句的方法
  10. Linux程序包管理之rpm