PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式
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库)实现观察者模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转载】从30岁到35岁,为你的生命多积
- 下一篇: php变量什么情况下加大括号{}