编程/13 分钟阅读

PHP 程序设计之观察者模式的实现

什么是观察者模式?

一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些 观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一 个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。

观察者模式有什么用?

上面的一段文字可能说的太过书面化,但是任何设计模式都是脱胎于实际的场景中,只要理解什么情况下需要用这种模式,基本就理解这种模式是干什么用的。比如用户登录这一行为,可能会产生积分赠送、登录日志写入、通知好友等等一系列操作。但是积分和日志以及通知模块通常是独立的。是否启用登录送积分,登录日志是否写入,通知哪些好友又是需要管理员可控的。并且要考虑后续程序功能模块的删改,所以按照正常类继承写法无疑对后续开发产生许多不可控的影响。于是,这时候就需要使用观察者模式。许多开源程序的插件机制,主题机制都是基于这种模式。

观察者模式要怎么实现?

既然是观察者模式,肯定有观察者和被观察者。首先我们把他们抽象出来。然后根据上面提出的问题,针对用户登录这一行为,实现观察者模式。

//抽象一个被观察者,并指定必要的抽象方法
	abstract class observed{
		//添加观察者,限制参数
		abstract public function attach(observer $observer,$type);
		//删除观察者
		abstract public function detach(observer $observer,$type);
		//通知
		abstract public function notify($type);		
	}
	//抽象一个观察者,并指定抽象方法
	abstract class observer{
		abstract public function update(observed $observed,$type);
	}

然后我们分别实例化一个被观察者和两个观察者,并实现其方法

//实例化一个被观察者对象,并实现抽象方法
	class user extends observed{
	    CONST OBSERVER_TYPE_REGISTER = 1;//注册
	    CONST OBSERVER_TYPE_LOGIN = 2;//登录	
		//保存观察者
		private $observers;
		public $name;
		//注意,实现抽象方法时可见性只能大于或者等于抽象方法
		function attach(observer $observer,$type){
			$this->observers[$type][] = $observer;
		}
		function detach(observer $observer,$type){
			if($idx = array_search($observer, $this->observers[$type], true)){
				unset($this->observers[$type][$idx]);
			}
		}
		//满足条件则通知观察者
		function notify($type){
			if(!empty($this->observers[$type])){
				foreach($this->observers[$type] as $observer){
				    $observer->update($this,$type);
				}				
			}
		}
		//模拟登录方法
		function login($name){
			$this->name=$name;
			//添加观察者[技巧:如果使用插件,则循环添加当前开启的插件即可]
			$point=new point();
			$this->attach($point,self::OBSERVER_TYPE_REGISTER);
			$log=new log();
			$this->attach($log,self::OBSERVER_TYPE_REGISTER);
			//通知观察者
			$this->notify(self::OBSERVER_TYPE_REGISTER);
		}
	}
	//实例化观察者[积分]
	class point extends observer{
	    public function update(observed $observed,$type){
	    	if($type==1){	//登录处理
				echo 'login:add point '.$observed->name.'<br>';
	    	}
	    }		
	}
	//实例化观察者[日志]
	class log extends observer{
	    public function update(observed $observed,$type){
	    	if($type==1){	//登录处理
				echo 'log:write log for '.$observed->name.'<br>';
	    	}
	    }		
	}

在user中我们多增加了一个login方法来模拟登录这一行为。

//模拟登录
	$user=new user();
	$user->login('name');

执行之后我们会看到结果

login:add point name log:write log for name

看到这里可能大家就明白了。观察者模式就是一个事件系统,一个对象去观察另一个对象的行为,并做出相应的处理。来避免各功能块之间的耦合,实现“低耦合”、“高聚合”这一概念

发表评论

0 条评论

暂无评论