PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式
SPL(標(biāo)準(zhǔn)PHP庫(kù) - Standard PHP Library)是PHP5面向?qū)ο蠊δ苤兄匾牟糠帧T慕忉屖沁@樣的“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.
觀察者模式是一種簡(jiǎn)單的事件系統(tǒng),包含了兩個(gè)或更多的互相交互的類。這一模式允許某個(gè)類觀察另一個(gè)類的狀態(tài),當(dāng)被觀察類的狀態(tài)發(fā)生變化時(shí),這個(gè)模式會(huì)得到通知。被觀察的類叫subject,負(fù)責(zé)觀察的類叫做Observer 。PHP 提供的 SplSubject 和 SplObserver接口可用來(lái)表達(dá)這些內(nèi)容。
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類維護(hù)了一個(gè)特定狀態(tài),當(dāng)這個(gè)狀態(tài)發(fā)生變化時(shí),他就會(huì)調(diào)用notify方法,所以之前使用attach注冊(cè)的splobserver實(shí)例的update就會(huì)被調(diào)用。這里我們實(shí)現(xiàn)一個(gè)簡(jiǎn)單地觀察者模式的例子
<?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)上例中我們通過(guò)數(shù)組存儲(chǔ) observer對(duì)象,使用數(shù)組及可能會(huì)出現(xiàn)兩個(gè)問(wèn)題:
1、同一個(gè)observer可能會(huì)被加載多次,導(dǎo)致多次調(diào)用同一個(gè)對(duì)象的update方法。
2、detach中需要通過(guò)迭代或者搜索數(shù)組來(lái)找到要?jiǎng)h除的observer對(duì)象,導(dǎo)致運(yùn)行效率降低。
SplObjectStorage類
PHP5提供了SplObjectStorage類,在這里我們可以用來(lái)存儲(chǔ)observer對(duì)象,SplObjectStoraged的實(shí)例就像一個(gè)數(shù)組,但是他所存放的對(duì)象是唯一的。SplObjectStorage還可以使用detach直接從集合中刪除指定的對(duì)象而不用遍歷或搜索整個(gè)集合。下面看一個(gè)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這個(gè)集合中只有1個(gè)calssa,盡管我們添加了兩次。并且沖集合中刪除一個(gè)元素也變得極為簡(jiǎn)單,拿上面的代碼來(lái)說(shuō),只需使用$ObjectStorage->attach($a);即可輕松的將$a從集合中移除。
結(jié)合 SplObjectStorage 我們?cè)賮?lái)修改最上面那個(gè)觀察者模式的例子
<?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)?
轉(zhuǎn)載于:https://www.cnblogs.com/kelsen/p/3791761.html
總結(jié)
以上是生活随笔為你收集整理的PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【转载】从30岁到35岁,为你的生命多积
- 下一篇: shell脚本实现无密码交互的SSH自动