今天来介绍一个很有用的设计模式,“观察者模式”,顾名思义,既然有“观察者”, 那么一定就有“被观察者”,从这个层面可以理解到,在这个设计模式中有两个对象, 一个是主体对象,一个是客体对象,在实际的代码实现上实际是“被观察者”主动通知了“观察者”。“被观察者”是主体对象,现在看不懂没关系,把下面的代码抄几遍就懂了。
PHP 提供了两个内置接口来帮助实现“观察者模式”, 其中“被观察者”需要实现 SplSubject
接口,“观察者”需要实现SplOberver
。
来看一个例子:
<?php
class PluginA implements SplObserver {
public function update(\SplSubject $subject) {
echo "Plugin A ".$subject->user['name'].' is registering.'.PHP_EOL;
}
}
class PluginB implements SplObserver {
public function update(\SplSubject $subject) {
echo "Plugin B ".$subject->user['name'].' is registering.'.PHP_EOL;
}
}
class User implements SplSubject {
private $observers = [];
public $user=[];
public function register($name, $password){
$this->user['name'] = $name;
$this->user['password'] = $password;
$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');
将以上代码保存即可运行。
以上代码模拟了一个调用注册方法register
时,通知相关插件执行相应任务的机制。它使用观察者模式实现了插件的机制。
插件对象PluginA
和PluginB
的实例就是“观察者”,User
类的实例 $user
是“被观察者”,“观察者”需要通过 attach
方法注册到“被关观察者” 上,
当register
方法被时,User
会通过notify
方法来通知所有的插件,并将主体对象即被观察者传递给插件。
这里仅仅是通过最简单的代码展示了什么是观察者模式,如果想实现插件,我们应该能传递更多的信息给插件,比如我们想在插件中针对主体对象的发生不同事件(不同的方法被调用)做不同的处理,我们可能需要“事件”的概念,你知道如何实现么?
可以试着自己写一下,或者请看下一篇吧。
转载请注明:大后端 » PHP设计模式之——观察者模式