观察者模式

观察者模式包含 被观察者(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),第二个参数为通知的信息。

 

posted @ 2017-10-28 15:36  寻觅beyond  阅读(245)  评论(0编辑  收藏  举报
返回顶部