上一篇通过一个简单的例子介绍了下什么是观察者模式,在实际的业务中,观察者应该对不同的情况做出不同的发应,这个其实很简单,我们加一个给主体对象加一个event
的属性就ok了。
看对上一篇修改后的代码,可以自己对比下,改动并不大:
<?php
/**
* 支持了事件的版本
*/
class PluginA implements SplObserver {
public function update(\SplSubject $subject) {
if($subject->event == 'register') {
echo "Plugin A ".$subject->user['name'].' is registering.'.PHP_EOL;
}
}
}
class PluginB implements SplObserver {
public function update(\SplSubject $subject) {
if($subject->event == 'register'){
echo "Plugin B ".$subject->user['name'].' is registering.'.PHP_EOL;
}
if($subject->event == 'login') {
echo "Plugin B ".$subject->user['name']. ' is logining.'.PHP_EOL;
}
}
}
class User implements SplSubject {
public $event;
private $observers = [];
public $user=[];
public function register($name, $password){
$this->user['name'] = $name;
$this->user['password'] = $password;
$this->event = 'register';
$this->notify();
}
public function login($name, $password) {
$this->user['name'] = $name;
$this->user['password'] = $password;
$this->event = 'login';
$this->notify();
}
public function attach(\SplObserver $observer) {
array_push($this->observers, $observer);
}
public function detach(\SplObserver $observer) {
$index = array_search($observer, $this->observers, true);
if ($index){
unset($this->observers[$index]);
}
}
public function notify(){
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
}
//-- 实例化主体对象
$user = new User();
//-- end
//-- 注册插件
$plugins = [
new PluginA(),
new PluginB(),
];
foreach ($plugins as $plugin) {
$user->attach($plugin);
}
//-- end
//-- 执行主体的业务代码
$user->register('shanhuhai', '123456');
$user->login('shanhuhai', '123456');
对比上一篇的代码,我们在notify之前都需要通过 $this->event='事件名'
,来指明本次notify 的事件是什么,这样在插件中就可以根据不同的事件做出相应的处理。
完成了这个之后你会发现一个问题,目前来看我必须将所有的插件实例化后才能注册到主体对象中,那么问题来了,如果一个插件,只处理部分事件,那么如果在整个程序处理过程中这个事件没有被触发,那么这个插件的实例化是不是浪费了?
为了解决这个问题,我们在下一篇会将代码做大幅改动,基本是为了在具体知道那个事件被触发了以后才去实例化相应的要处理这个事件的插件。
转载请注明:大后端 » PHP设计模式之——观察者模式(2)