zoukankan      html  css  js  c++  java
  • 观察者模式

    观察者模式包含 被观察者(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}
    ";
    		}
    	}
    	class CleanerObserver{
    		public function update($str){//当发生变化时,进行的操作
    			echo "I'm do some cleaning when {$str}
    ";
    		}
    	}
    
    	//创建一个被观察着(被订阅的对象)
    	$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}
    ";
    		}
    	}
    	class CleanerObserver{
    		public function update($str){//当发生变化时,进行的操作
    			echo "I'm do some cleaning when {$str}
    ";
    		}
    	}
    
    	//创建一个被观察着(被订阅的对象)
    	$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),第二个参数为通知的信息。

  • 相关阅读:
    hdu
    《Linux命令行与shell脚本编程大全》 第十四章 学习笔记
    zoj 3665 Yukari's Birthday(枚举+二分)
    ActiveMQ使用STOMP协议的一个错误问题:Unexpected ACK received for message-id
    Ubuntu下屏幕录像、后期处理不完全攻略
    find-all-numbers-disappeared-in-an-array
    find-right-interval
    non-overlapping-intervals
    cut命令如何截取以空格隔开的字段
    arranging-coins
  • 原文地址:https://www.cnblogs.com/-beyond/p/7747088.html
Copyright © 2011-2022 走看看