Design Pattern - Observer Pattern

0x00 Observer Pattern
Also called Publish/Subscribe Pattern (Publish/Subscribe).

Definition
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. (定义对象间一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新.)

Roles
Subject - Observed role, must be able to dynamically add and cancel observers, plays the role of observing observers and notifying observers.
Observer - Observer role, observers receive message notifications and update.
ConcreteSubject - Specific observed role, defines the observed’s own business logic, also defines which events to notify.
ConcreteObserver - Specific observer role, each specific observer’s own processing logic.

Advantages
Abstract coupling between observer and observed relationships, making it easy to extend.
Establish a trigger mechanism.

Disadvantages
When multi-level triggering, efficiency becomes poor.

PHP Implementation1
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?php
/*

  • observer pattern
  • /

//Observed
abstract class Subject {
private $observers = [];
public function addObserver(Observer $_observer)
{
array_push($this->observers, $_observer);
}

public function delObserver(Observer $_observer)
{
    $key = array_search($this->observers, $_observer);
    if ($key !== false) {
        array_splice($this->observers, $key, 1);
    }
}

// Notify all observers
public function notifyObservers()
{
    foreach($this->observers as $observer) {
        $observer->update();
    }
}

}

// Specific observed
class ConcreteSubjects extends Subject {
public function doSth()
{
parent::notifyObservers();
}
}

// Observer interface
interface Observer {
public function update();
}

class ConcreteObserver implements Observer {
public function update()
{
echo “Get it! Yes! Sir!”;
}
}

class Client {
public static function main()
{
$subject = new ConcreteSubjects();
$observers = new ConcreteObserver();
$subject->addObserver($observers);
$subject->doSth();
}
}
(new Client())::main();

Use Cases
Separable non-combination related behavior scenarios.
Multi-level event trigger scenarios.
Cross-system message exchange scenarios, like message queue processing mechanisms.

0x01 Summary
The Observer pattern needs to focus on solving two problems:

Broadcast chain - in an observer pattern, at most one object appears as both observer and observed, meaning messages are forwarded at most once (forwarded twice) is appropriate and well-controlled.
Asynchronous processing - need to consider thread safety and queues.