Home >Backend Development >PHP Tutorial >PHP object-oriented advanced design patterns: Observer pattern usage examples
What is the observer pattern?
The observer design pattern makes it easier to create objects that view the state of target objects, and provides specified functionality that is uncoupled from core objects.
The pattern is very simple: an object makes itself observable by adding a method that allows another object, the observer, to register itself. 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.
##UML
This diagram details a class design using the Observer design pattern: The following is a description of the above picture: 1.MyObject is an observable object, which contains an observer-protected array named observers. The public method addObserver() accepts an instance of an observer and stores it in the observer array. 2. The doSomething() public method will be called. This method applies state changes to MyObject. Subsequently, the notify() public method will be called, which can traverse the loop observer array. 3.MyObjectObserver has a public method named change(), which accepts an instance of MyObject. This particular observer will then perform some action on the contents of MyObject. When a specific observer is found in the observer array, MyObject's notify() method directly calls the change() method. Usage example:<?php interface Observable{ function attach( Observer $observer ); function detach( Observer $observer ); function notify(); } class login implements Observable{ const LOGIN_USER_UNKNOW = 1; const LOGIN_WRONG_PASS = 2; const LOGIN_ACCESS = 3; private $status = array(); private $observers = array(); public function setStatus( $status, $user, $ip ) { $this->status = array( $status, $user, $ip ); } public function getStatus() { return $this->status; } public function handleLogin( $user, $pass, $ip ) { switch ( mt_rand( 1, 3 ) ) { case 1: $this->setStatus( self::LOGIN_USER_UNKNOW, $user, $ip ); $ret = false; break; case 2: $this->setStatus( self::LOGIN_WRONG_PASS, $user, $ip ); $ret = false; break; case 3: $this->setStatus( self::LOGIN_ACCESS, $user, $ip ); $ret = true; break; } $this->notify(); return $ret; } public function attach( Observer $observer ) { $this->observers[] = $observer; } public function detach( Observer $observer ) { $newObservers = array(); foreach ( $this->observers as $obs ) { if ( $obs !== $observer ) $newObservers[] = $obs; } $this->observers = $newObservers; } public function notify() { foreach ( $this->observers as $obs ) { $obs->update( $this ); } } } interface Observer{ function update( Observable $observable ); } class SecurityMonitor implements Observer{ function update( Observable $observable ) { $status = $observable->getStatus(); if($status[0] == Login::LOGIN_WRONG_PASS){ echo __CLASS__.":".$status[1]."于".$status[2]."登录失败"; } } } $login = new Login(); $login->attach(new SecurityMonitor()); $login->handleLogin('XXX','XXX','127.0.0.1'); ?> 出错时的运行结果: SecurityMonitor:XXX于127.0.0.1登录失败[Finished in 0.1s]You can see in the code that the login object actively adds the SecurityMonitor object for observation. In this way, to call Login::getStatus(), the SecurityMonitor class must know more information. Although the call occurs on an ObServable object, there is no guarantee that the object is also a Login object. To solve this problem, there is a way: keep the ObServable interface generic intermittently, and the ObServer class is responsible for ensuring that their bodies are of the correct type. They can even add themselves to the subject.
The above is the detailed content of PHP object-oriented advanced design patterns: Observer pattern usage examples. For more information, please follow other related articles on the PHP Chinese website!