Joomla设计模式-观察者模式
知道joomla的人都清楚Joomla的插件机制是观察者模式实现的。那么究竟什么是观察者模式呢?如何用代码来实现观察者模式呢?
观察者模式有两个概念。一个是主题。一个是观察者。举一个例子来说明这两个概念。
你向一个报社订了一份报纸,隔壁的张三也想报社订了一份报纸。然后每天你都会收到该报社送来的报纸。当然隔壁的张三能会收到。在这期间,只要他们已有报纸都会主动送来,除非你打电话去取消订阅。
在这个事情中,报社的就是主题。而你和张三就是两个观察者。因为你们订阅了报纸(向主题注册了),报社就会自动送报纸给你(当主题有内容更新的时候就会通知观察者)。
通过上面的过程,我们可以看见,其实观察者模式解决的是对象之间的一对多的依赖。当一个对象改变状态的时候,其他依赖者都会收到通知。
在joomla中,只输出一个页面的过程中,会触发很多事件,比喻说加载内容完成。当这些事件触发的时候,系统就会自动调用关注这一事件的观察者们。(你可以修改文章内容)。
那么如何用PHP来实现观察者模式呢?
对如一个主题,他应该实现至少3个方法,一个观察者至少要实现一个方法。
interface subject { public function registerObserver( observer $o); //注册为观察者 public function removeObserver( observer $o); //删除观察者 public function notifyObservers(); //通知观察者 } interface observer { public function update(); //更新 }
上面代码中定义了主题和观察者接口。我们的自己写的主题只需要实现subject接口即可。观察者只需实现observer接口。
如果我们要实现一个文章内容变化的主题,那么我们可以这样写代码:
class contentSubject implements subject { private $observers=array();//用于记录所有观察者的变量 public function contentSubject() { echo "subject ok<br />"; } public function registerObserver(observer $o) { array_push($this->observers ,$o); //将观察者放到数组中 } public function removeObserver( observer $o) { unset( $this->observers[array_search($o,$this->observers) ]);//删除一个观察者 } public function notifyObservers() //通知所有的观察者 { foreach ($this->observers as $observer) { $observer->update(); } } }
上面的就基本实现了一个主题。我们用数组来作为观察者的容器。下面就是实现观察者了。
class zmaxObserver implements observer { private $subject = null; //subject public function zmaxObserver(contentsubject $contentSubject) { $this->subject = $contentSubject; $contentSubject->registerObserver($this); } public function update() { echo "ZMAX I am update<br />"; } } class ztestObserver implements observer { private $subject = null; //subject public function ztestObserver(contentSubject $contentSubject) { $this->subject = $contentSubject; $this->subject->registerObserver($this); } public function update() { echo "ZTest I am update<br />"; } }
//上面实现了两个观察者。非常的简单。在构造观察者 时候需要指定一个需要观察的主题,并且向主题注册。这样我们基本上就能够做到和主题解偶,并且又能从主题获得数据。的确是一个非常不错的模式。
下面是测试该模式的代码:
echo "Test for overser pattern!<br />"; $sub = new contentSubject(); $objZmax = new zmaxObserver($sub); $objZtest = new ZtestObserver($sub); $sub->notifyObservers(); $sub->removeObserver($objZmax); $sub->notifyObservers();
感觉非常的不错。如果我们再用一种机制将观察者和主题分开为不同的文件。那么就可以实现出joomla的插件机制了。