Intention:
Defines a one-to-many dependency between objects, and when the state of an object changes, all objects that depend on it are notified and automatically updated "GOF95"
Also known as publish-subscribe (publish-subscribe) mode, model-view (model-view) mode, source-monitor (Source-listener) mode, or dependent (dependents) mode
Structure Chart:
Main roles
Abstract theme (Subject) role: The theme role holds all references to the Observer object in a collection, each subject can have any number of observers. Abstract topics provide an interface for adding and removing observer objects.
Abstract observer (OBSERVER) role: Defines an interface for all specific observers, updating themselves when the subject of the observation changes.
Specific theme (ConcreteSubject) role: Store related states to specific observer objects, and notify all registered observers when the internal state of the specific subject changes. Specific theme roles are usually implemented with a specific subclass.
The specific observer (Concretedobserver) Role: stores a specific Subject object, stores the associated state, and implements the update interface required by the abstract observer role to keep its state and subject state consistent.
Advantages and Disadvantages
Advantage: The degree of coupling between the observer and the subject is small, which supports broadcast communication.
Disadvantage: Because the observer is unaware of the existence of other observers, it may be ignorant of the ultimate cost of changing the target. This may cause unexpected updates.
Applicable scenarios
When an abstract model has two aspects, one aspect is dependent on another.
When a change to an object needs to change the other object at the same time, do not know how many objects to change.
When an object must notify other objects, it cannot assume that the other object is. In other words, you don't want these objects to be tightly coupled.
Implementation code
<?php
/**
* Observer mode
* @package Design
*/
/**
* Abstract Theme Roles
*/
Interface Subject {
/**
* Add a new Observer object
* @param Observer $observer
*/
Public function Attach (Observer $observer);
/**
* Delete a registered Observer object
* @param Observer $observer
*/
Public Function Detach (Observer $observer);
/**
* Notify all registered Observer objects
*/
Public function notifyobservers ();
}
/**
* Specific Theme Roles
*/
Class ConcreteSubject implements Subject {
Private $_observers;
Public Function __construct () {
$this->_observers = Array ();
}
/**
* Add a new Observer object
* @param Observer $observer
*/
Public function Attach (Observer $observer) {
Return Array_push ($this->_observers, $observer);
}
/**
* Delete a registered Observer object
* @param Observer $observer
*/
Public Function Detach (Observer $observer) {
$index = Array_search ($observer, $this->_observers);
if ($index = = FALSE | |! array_key_exists ($index, $this->_observers)) {
return FALSE;
}
unset ($this->_observers[$index]);
return TRUE;
}
/**
* Notify all registered Observer objects
*/
Public Function notifyobservers () {
if (!is_array ($this->_observers)) {
return FALSE;
}
foreach ($this->_observers as $observer) {
$observer->update ();
}
return TRUE;
}
}
/**
* Abstract Observer role
*/
Interface Observer {
/**
* Update method
*/
Public function update ();
}
Class Concreteobserver implements Observer {
/**
* Name of the Observer
* @var <type>
*/
Private $_name;
Public function __construct ($name) {
$this->_name = $name;
}
/**
* Update method
*/
Public Function Update () {
Echo ' Observer ', $this->_name, ' has notified.<br/> ';
}
}
$subject = new ConcreteSubject ();
* * ADD first observer/
$observer 1 = new Concreteobserver (' Martin ');
$subject->attach ($observer 1);
Echo ' <br/> The ' notify:<br/> ';
$subject->notifyobservers ();
* * Add a second observer/
$observer 2 = new Concreteobserver (' Phppan ');
$subject->attach ($observer 2);
Echo ' <br/> The Second notify:<br/> ';
$subject->notifyobservers ();
/* Delete the first observer * *
$subject->detach ($observer 1);
Echo ' <br/> The third notify:<br/> ';
$subject->notifyobservers ();