观察者模式
观察者模式包含 被观察者(Subject) 和观察者(Observer),一个被观察者可能被多个观察者观察,一旦被观察着发生改变,就会触发相应的机制来通知观察者,告诉观察者 被观察者发生了改变,然后观察者根据被观察者的变化进行下一步动作。
举一个例子:
在一个公司中,老板有个秘书,秘书和老板在总经理办公室,其他职员都在公共空间办公,这个秘书和外面的职员关系特别好,外面的职员和秘书打个招呼,一旦老板有什么动静,就通知他们:每次老板来了,他就会给外面的职员发信息,说老板来了,都收敛点,要是老板走了,大家就放松一下。
在这个例子中,秘书就是subject,其他职员就是observer,其他职员订阅了这个秘书(秘书将职员加入名单中即可),一旦老板有动静,秘书就发出Notify(message),message会传给每个订阅他的职员(observer),然后,职员的行为就会根据信息改变---即调用update()方法。
来看代码吧:
<?php class Secretary{ public $_observers=array();//保存订阅者(即观察者数组) public function AddObserver($observer){ $this->_observers[]=$observer; } public function Notify($info){//发出通知 foreach($this->_observers as $obv){ //通过循环,将信息传递给观察者数组中的所有观察者 //观察者的update方法收到信息之后,进行相应的操作 $obv->update($info); } } } class WorkerObserver{ public function update($str){//当发生变化时,进行的操作 echo "I'm working hard when {$str}\n"; } } class CleanerObserver{ public function update($str){//当发生变化时,进行的操作 echo "I'm do some cleaning when {$str}\n"; } } //创建一个被观察着(被订阅的对象) $secretary=new Secretary(); //创建多个观察者 $w=new WorkerObserver(); $c=new CleanerObserver(); //观察者进行订阅:将观察者加入到被观察者的_observers数组中 //只有加入被观察者的_observers数组中,才能收到信息 $secretary->AddObserver($w); $secretary->AddObserver($c); //有新动作,于是被观察者发出信息,信息将传递给每一个订阅过他的观察者 //也即自己_observers数组中保存的observer $secretary->Notify("the boss coming"); ?>
结合上面的讲解,然后再看代码,绝对能够理解。当有多个观察者类,然后每个观察者类都实例化了多个观察者对象,并且所有实例化的对象全都订阅了被观察者,这是要想要通知所有对象,只需将被订阅者(subject)对象中的$_observers数组改为二维数组即可,第一层为各个观察者类(类别),第二层为各观察者类(类别)的对象,代码如下:
<?php class Secretary{ public $_observers=array();//保存订阅者(即观察者数组) public function AddObserver($type,$observer){ $this->_observers[$type][]=$observer; } public function Notify($info){//发出通知 //通过两个循环,将信息传递给观察者数组中的所有观察者 //观察者的update方法收到信息之后,进行相应的操作 foreach($this->_observers as $type){ foreach($type as $obv){ $obv->update($info); } } } } class WorkerObserver{ public function update($str){//当发生变化时,进行的操作 echo "I'm working hard when {$str}\n"; } } class CleanerObserver{ public function update($str){//当发生变化时,进行的操作 echo "I'm do some cleaning when {$str}\n"; } } //创建一个被观察着(被订阅的对象) $secretary=new Secretary(); //创建多个观察者 $w1=new WorkerObserver(); $w2=new WorkerObserver(); $c1=new CleanerObserver(); $c2=new CleanerObserver(); //观察者进行订阅:将观察者加入到被观察者的_observers数组中 //只有加入被观察者的_observers数组中,才能收到信息 $secretary->AddObserver("worker",$w1); $secretary->AddObserver("worker",$w2); $secretary->AddObserver("cleaner",$c1); $secretary->AddObserver("cleaner",$c2); //有新动作,于是被观察者发出信息,信息将传递给每一个订阅过他的观察者 //也即自己_observers数组中保存的observer $secretary->Notify("the boss coming"); ?>
被观察者的Notify方法可以传递两个参数,第一参数为某一类的观察者(比如只通知worker),第二个参数为通知的信息。
如需转载,请注明文章出处,谢谢!!!