PHP,DDD,CQRS,Event Sourcing,Kubernetes,Docker,Golang

0%

了解PHP设计模式之观察者模式

观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作,观察者模式提供了避免组件之间紧密耦合的另一种方式。

在观察者模式中,被观察者称为subject,观察者称为observer,为了表达这些内容,SPL(Standard PHP Libaray)提供了SplSubject(被观察者)和SplObserver(观察者)两个接口。在编写观察者模式时,只要实现这两个接口即可。接口如下:

1
2
3
4
5
6
7
8
9
10
 //被观察者接口
interface SplSubject{
public function attach(SplObserver $observer);//注册观察者(注册的观察者:当我(被观察者)的某个状态改变时,需要通知的对象)
public function detach(SplObserver $observer);//释放观察者
public function notify();//通知所有注册的观察者的方法
}
//观察者接口
interface SplObserver{
public function update(SplSubject $subject);//观察者进行更新状态
}

这一模式的概念是SplSubject类维护了一个特定状态,当这个状态发生变化时,它就会调用notify()方法。调用notify()方法时,所有之前使用attach()方法注册的SplObserver实例的update方法都会被调用。 以下是实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  <?php
//被观察者实现类
class DemoSubject implements SplSubject {
private $observers; //存放观察者的类
private $value;
public function __construct() {
$this->observers = array();
}
//注册观察者
public function attach(SplObserver $observer) {
$this->observers\[\] = $observer;
}
//释放观察者
public function detach(SplObserver $observer) {
if($idx = array_search($observer,$this->observers,true)) {
unset($this->observers\[$idx\]);
}
}
//通知所有观察者,执行观察者类中的update方法
public function notify() {
foreach($this->observers as $observer) {
$observer->update($this);
}
}
/*设置状态,当状态发生任何变化时,都会调用notify方法通知所有的观察者,即调用观察者类中的update方法*/
public function setState($value) {
$this->value = $value;
$this->notify();
}
//
public function getValue() {
return $this->value;
}
}
//观察者简单类
class DemoObserver implements SplObserver {
//接收被观察者发送的通知
public function update(SplSubject $subject) {
echo 'The new value is '. $subject->getValue();
}
}
$subject = new DemoSubject();//初始化被观察者
$observer = new DemoObserver();//初始化一个观察者
$subject->attach($observer);//添加一个观察者
$subject->setState(5);//被观察者修改状态。
?>;

输出结果为: The new value is 5 观察者模式的优点在于,挂接到被观察者上的观察者可多可少,并且不需要提前知道哪个观察者会响应被观察者发出的响应事件。 这种设计模式在很多PHP框架中都被使用到,如Yii等。