First understand the concept of the Observer Pattern: an object allows another object to , that is, the observer registers itself) to make itself observable. When an observable object changes, it sends messages to registered observers. These observers use this information to perform operations independent of the observable object. The result is that objects can talk to each other without having to understand why. The observer pattern is an event system, which means that this pattern allows a class to observe the state of another class. When the state of the observed class changes, the observing class can receive notifications and take corresponding actions; observation The operator pattern provides you with the ability to avoid tight coupling between components.
UML structure diagram:
Problems solved by the observer pattern
During our development process, we should have more or less encountered the problem that changing part of the code will cause a series of other changes. Obviously it is impossible to completely avoid this situation, but we should also try to reduce it as much as possible. Dependence on other components, and the observer pattern is to solve this problem.
For example, we have a post object with the following code:
class Post { protected $_userid = null; protected $_ip = null; protected $_content = null; function __construct() { // ... } // 发帖方法 public function addPost() { // ... 发帖逻辑 } }
The above is an ordinary post object. As the number of posts and visits increased, the operators began to stop working, and the company often received complaint calls saying that our website contained a lot of sensitive content and garbage. Advertising, so we need to do content review: first, review of users, some blacklisted users should be banned from posting; second, review of IP; third, review of sensitive words in the content. So our code looks like this:
class Post { protected $_userid = null; protected $_ip = null; protected $_content = null; function __construct() { } public function addPost() { if (!Postscan::checkUserid($tihs->_userid)) { return false; } if (!Postscan::ipUserid($tihs->_ip)) { return false; } if (!Postscan::checkContent($tihs->_content)) { return false; } // ... } }
As more and more fields need to be reviewed, the addPost method becomes longer and longer, and the publishing object can only be tightly embedded in the system.
Implementation of Observer Pattern
The core of the observer pattern is to separate the observer from the subject. When the subject knows that an event occurs, the observation needs to be notified. At the same time, we do not want to write down the relationship between the subject and the observer, so we Let’s modify our code above:
//主体必须实现的接口 interface Observable { public function attach(Observer $observer); public function detach(Observer $observer); public function notify(); } //观察者必须实现的接口 interface Observer { public function do(Observable $subject); } class Post implements Observable { protected $_userid = null; protected $_ip = null; protected $_content = null; protected $_observerlist = array(); function __construct() { } public function attach(Observer $observer) { $this->_observerlist[] = $observer; } public function detach(Observer $observer) { foreach ($this->_observerlist as $key => $value) { if ($observer === $value) { unset($this->_observerlist[$key]) } } } public function notify() { foreach ($this->_observerlist as $value) { if (!$value->do($this)) { return false; } } return true; } public function addPost() { if (!$this->notify()) { return false; } // ... } }
With the above code, we can easily add audit rules.
SPL code
The observer pattern is a very common and commonly used design pattern, so much so that the SPL extension has encapsulated the corresponding classes and methods for us. The following code is based on the three elements provided by SPL: SplObserver, SplSubject, SplObjectStorage Implemented code
class Post implements SplSubject { protected $_userid = null; protected $_ip = null; protected $_content = null; protected $_storage = new SplObjectStorage(); function __construct() { } public function attach(SplObject $observer) { $this->_storage->attach($observer); } public function detach(SplObject $observer) { $this->_storage->detach($observer); } public function notify() { foreach ($this->_storage as $value) { if (!$value->update($this)) { return false; } } return true; } public function addPost() { if (!$this->notify()) { return false; } // ... } }
It’s very simple. The most important thing is to understand that in this example, we have separated some review methods from the post class, and the post object can also be used as other publishing types.
The implementation of the above content is the observer mode of PHP design pattern introduced by the editor to you. I hope it will be helpful to everyone!