什么是观察者模式?
一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些 观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一 个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。
观察者模式有什么用?
上面的一段文字可能说的太过书面化,但是任何设计模式都是脱胎于实际的场景中,只要理解什么情况下需要用这种模式,基本就理解这种模式是干什么用的。比如用户登录这一行为,可能会产生积分赠送、登录日志写入、通知好友等等一系列操作。但是积分和日志以及通知模块通常是独立的。是否启用登录送积分,登录日志是否写入,通知哪些好友又是需要管理员可控的。并且要考虑后续程序功能模块的删改,所以按照正常类继承写法无疑对后续开发产生许多不可控的影响。于是,这时候就需要使用观察者模式。许多开源程序的插件机制,主题机制都是基于这种模式。
观察者模式要怎么实现?
既然是观察者模式,肯定有观察者和被观察者。首先我们把他们抽象出来。然后根据上面提出的问题,针对用户登录这一行为,实现观察者模式。
//抽象一个被观察者,并指定必要的抽象方法
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 条评论