Core points
update()
, attach()
, detach()
, and setState()
are used to manage observers and notify them of status changes. notify()
Observer mode
Observer pattern (also known as publish-subscribe pattern) is a behavioral design pattern that defines one-to-many relationships between objects so that when an object changes its state, all dependent objects are automatically notified and updated. In my case, I used this mode to link the authentication mechanism of the portal with the forum software. The behavior of logging into the portal will also automatically trigger the user to log into the forum. Objects that have a one-to-many relationship with other objects interested in their own state are calledtopic or Publisher . Its dependency object is called the observer or the subscriber. Whenever the state of the subject changes, the observer is notified and can act accordingly. A topic can have any number of dependent observers that will send notifications to those observers, and any number of observers can subscribe to the topic to receive such notifications.
Observer categoryThe Observer class provides a
method that the subject will call to inform its state changes. In this example, I have defined the update()
method as a specific method. If you want, you can define the method as an abstract method here and then provide a concrete implementation for it in the observer's subclass. update()
<?php abstract class Observer { public function __construct($subject = null) { if (is_object($subject) && $subject instanceof Subject) { $subject->attach($this); } } public function update($subject) { // 查找具有状态名称的观察者方法 if (method_exists($this, $subject->getState())) { call_user_func_array(array($this, $subject->getState()), array($subject)); } } }
Method accepts instances of observable topics and attaches itself to the topic—I will talk about it later. The __construct()
method retrieves the current state of the topic and uses it to invoke a subclassed observer method with the same state name. So in my specific case, I need to make the existing Auth class of the portal as an observable topic and create a concrete observer subclass to connect to the authentication code of the forum. My subclass also needs to implement the method using the state of the topic. update()
Theme category The subject class is also an abstract class, which defines four main methods:
,, attach()
, detach()
and setState()
. For convenience, I also added the notify()
and getState()
methods here. getObservers()
<?php abstract class Subject { protected $observers; protected $state; public function __construct() { $this->observers = array(); $this->state = null; } public function attach(Observer $observer) { $i = array_search($observer, $this->observers); if ($i === false) { $this->observers[] = $observer; } } public function detach(Observer $observer) { if (!empty($this->observers)) { $i = array_search($observer, $this->observers); if ($i !== false) { unset($this->observers[$i]); } } } public function getState() { return $this->state; } public function setState($state) { $this->state = $state; $this->notify(); } public function notify() { if (!empty($this->observers)) { foreach ($this->observers as $observer) { $observer->update($this); } } } public function getObservers() { return $this->observers; } }
Method subscribes the observer to a topic so that any state changes can be communicated to it. The attach()
method unsubscribes the observer from the topic so that it no longer observes the state changes of the topic. The detach()
method sets the current state of the topic and calls setState()
to update the observer, that is, to issue a notification to each observer. The notify()
methods update each subscribed object by iterating through the internal list and calling the notify()
method of each member in turn. The update()
and getState()
methods are just helper functions that return the status of the current topic and the observer list. getObservers()
Add carefully...integrate together
Now with the abstract base class for observers and topics, I was able to integrate the forum software into my existing web portal. I need to set the Auth class of the portal to be observable topic and set its observable state when the user logs in or logs out of the portal.
<?php class Auth extends Subject { function login() { // 执行登录身份验证的现有代码 // ... // 向任何观察者发出信号,表明用户已登录 $this->setState("login"); } function logout() { // 执行用户注销时执行某些操作的现有代码 // 例如销毁会话等... // 向任何观察者发出信号,表明用户已注销 $this->setState("logout"); } }
in the login()
and logout()
methods. To subclass the observer, I created an Auth_ForumHook class that is responsible for calling the forum's API login and logout functions. setState()
<?php class Auth_ForumHook extends Observer { function login($subject) { // 调用论坛的 API 函数以登录用户 // ... } function logout($subject) { // 调用论坛的 API 函数以注销用户 // ... } }
<?php abstract class Observer { public function __construct($subject = null) { if (is_object($subject) && $subject instanceof Subject) { $subject->attach($this); } } public function update($subject) { // 查找具有状态名称的观察者方法 if (method_exists($this, $subject->getState())) { call_user_func_array(array($this, $subject->getState()), array($subject)); } } }
This is all my extra coding needs besides preparing abstract Observer and Subject classes. Any state changes triggered by Auth's login()
and logout()
methods will notify the Auth_ForumHook observer and automatically log in or log out of the user in the forum. To add a new observer, for example, to log in to the tracker to record when a user logs in or logs out of the portal, simply provide a specific Observer class and attach it to the Auth topic without further modifying the login()
and logout()
methods of the existing Auth object.
Summary
If you have multiple objects that depend on another object and need to perform operations when the state of that object changes, or one object needs to notify other objects without knowing who or how many they are, then Observer pattern is a suitable and applicable design pattern. In this article, I show you the basic topic-observer pattern and provide concrete examples of how to easily extend the functionality of an existing class using this behavior pattern without tightly coupling any new requirements. This pattern allows you to achieve a higher level of consistency between related and dependent objects without sacrificing the reusability of your code.
Pictures from JPF / Shutterstock
(The subsequent FAQs section has been omitted due to the length of the article. The core content has been reorganized and polished on it.)
The above is the detailed content of Understanding the Observer Pattern. For more information, please follow other related articles on the PHP Chinese website!