Konzept
Das Beobachtermuster ist ein Verhaltensmuster, das eine Eins-zu-Viele-Abhängigkeitsbeziehung zwischen Objekten definiert, sodass alle davon abhängigen Objekte benachrichtigt und aktualisiert werden, wenn sich der Zustand eines Objekts ändert automatisch.
Wenn sich der Zustand eines Objekts ändert, wirkt sich dies auf die Änderungen mehrerer anderer Objekte aus. Zu diesem Zeitpunkt kann der Beobachtermodus verwendet werden.
Das Beobachtermuster entspricht dem Schnittstellenisolationsprinzip und erreicht eine lose Kopplung zwischen Objekten.
Alias
Publish-Subscribe
Model-View
Source-Listener
Rolle
Abstraktes Subjekt (Subjekt): Es speichert die Referenzen aller Beobachterobjekte in einer Sammlung, jedes Subjekt kann eine beliebige Anzahl von Beobachtern haben. Das abstrakte Thema bietet eine Schnittstelle zum Hinzufügen und Entfernen von Beobachterobjekten.
Konkretes Subjekt (ConcreteSubject): Speichern Sie den relevanten Status in einem bestimmten Beobachterobjekt. Wenn sich der interne Status des spezifischen Subjekts ändert, wird eine Benachrichtigung an alle registrierten Beobachter gesendet.
Abstrakter Beobachter (Beobachter): Definieren Sie eine Schnittstelle für alle konkreten Beobachter und aktualisieren Sie sich selbst, wenn sie vom Thema benachrichtigt werden.
Konkreter Beobachter: Implementiert die Aktualisierungsschnittstelle, die für die abstrakte Beobachterrolle erforderlich ist, um ihren eigenen Status mit dem Subjektstatus zu koordinieren.
UML-Diagramm
Code
Beispielcode
Die SplSubject- und SqlOberver-Schnittstellen wurden in PHP SPL bereitgestellt, Quellcode Wie folgt:
Nachfolgend schreiben wir unseren eigenen Code basierend auf diesen beiden Spl-Schnittstellen:/** * The <b>SplSubject</b> interface is used alongside * <b>SplObserver</b> to implement the Observer Design Pattern. * @link http://php.net/manual/en/class.splsubject.php */ interface SplSubject { /** * Attach an SplObserver * @link http://php.net/manual/en/splsubject.attach.php * @param SplObserver $observer <p> * The <b>SplObserver</b> to attach. * </p> * @return void * @since 5.1.0 */ public function attach (SplObserver $observer); /** * Detach an observer * @link http://php.net/manual/en/splsubject.detach.php * @param SplObserver $observer <p> * The <b>SplObserver</b> to detach. * </p> * @return void * @since 5.1.0 */ public function detach (SplObserver $observer); /** * Notify an observer * @link http://php.net/manual/en/splsubject.notify.php * @return void * @since 5.1.0 */ public function notify (); } /** * The <b>SplObserver</b> interface is used alongside * <b>SplSubject</b> to implement the Observer Design Pattern. * @link http://php.net/manual/en/class.splobserver.php */ interface SplObserver { /** * Receive update from subject * @link http://php.net/manual/en/splobserver.update.php * @param SplSubject $subject <p> * The <b>SplSubject</b> notifying the observer of an update. * </p> * @return void * @since 5.1.0 */ public function update (SplSubject $subject); }
<?php header('Content-type:text/html;charset=utf-8'); /** * Class Subject 主题 */ class Subject implements SplSubject { private $_observers = []; /** * 实现添加观察者方法 * * @param SplObserver $observer */ public function attach(SplObserver $observer) { if (!in_array($observer, $this->_observers)) { $this->_observers[] = $observer; } } /** * 实现移除观察者方法 * * @param SplObserver $observer */ public function detach(SplObserver $observer) { if (false !== ($index = array_search($observer, $this->_observers))) { unset($this->_observers[$index]); } } /** * 实现提示信息方法 */ public function notify() { foreach ($this->_observers as $observer) { $observer->update($this); } } /** * 设置数量 * * @param $count */ public function setCount($count) { echo "数据量加" . $count . '<br>'; } /** * 设置积分 * * @param $integral */ public function setIntegral($integral) { echo "积分量加" . $integral . '<br>'; } } /** * Class Observer1 观察者一 */ class Observer1 implements SplObserver { public function update(SplSubject $subject) { $subject->setCount(10); } } /** * Class Observer2 观察者二 */ class Observer2 implements SplObserver { public function update(SplSubject $subject) { $subject->setIntegral(10); } } /** * Class Client 客户端 */ class Client { /** * 测试方法 */ public static function test() { // 初始化主题 $subject = new Subject(); // 初始化观察者一 $observer1 = new Observer1(); // 初始化观察者二 $observer2 = new Observer2(); // 添加观察者一 $subject->attach($observer1); // 添加观察者二 $subject->attach($observer2); // 消息提示 $subject->notify();//输出:数据量加1 积分量加10 // 移除观察者一 $subject->detach($observer1); // 消息提示 $subject->notify();//输出:数据量加1 积分量加10 积分量加10 } } // 执行测试 Client::test();
数据量加10 积分量加10 积分量加10
Vorteile
Die Kopplung zwischen Beobachtern und Themen ist gering.
Unterstützt die Rundfunkkommunikation.
Nachteile
Da Beobachter nicht unwissend sind Aufgrund der Existenz anderer Beobachter kann es sein, dass es die letztendlichen Kosten einer Änderung des Ziels nicht kennt. Dies kann zu unerwarteten Updates führen.
Anwendbare Szenarien
Wenn ein abstraktes Modell zwei Aspekte hat, von denen einer vom anderen abhängt.
Wenn Änderungen an einem Objekt gleichzeitig Änderungen an anderen Objekten erfordern, ist nicht bekannt, wie viele Objekte geändert werden müssen.
Wenn ein Objekt andere Objekte benachrichtigen muss, kann es nicht davon ausgehen, wer die anderen Objekte sind. Mit anderen Worten: Sie möchten nicht, dass diese Objekte eng miteinander verbunden sind.