//+------------------------------------------------------------------+
//| 201111_091814.mq5 |
//| 2019-2020, dimitri pecheritsa |
//| 792112@gmail.com |
//+------------------------------------------------------------------+
//
// observer (push) - behavioral design pattern
//
// from: design patterns: elements of reusable object-oriented software
// by gof: erich gamma, richard helm, ralph johnson, john vlissides
// published in 1994
//
// intent
//
// define a one-to-many dependency between objects so that when one object
//changes state, all its dependents are notified and updated automatically
//
// applicability
//
// when an abstraction has two aspects, one dependent on the other.
//encapsulating these aspects in separate objects lets you vary and reuse
//them independently
// when a change to one object requires changing others, and you don't
//know how many objects need to be changed
// when an object should be able to notify other objects without making
//assumptions about who these objects are. in other words, you don't want
//these objects tightly coupled
//
// structure
//
// observers
// | Subject |---------------------->*|Observer|
// |----------------------| |--------|
// |Attach(Observer) | |Update()|
// |Detach(Observer) | ^
// |Notify() | |
// | forall o in observers| |
// | o.Update() | |
// ^ |
// | | ConcreteObserver |
// | subject |--------------------|
// | ConcreteSubject |<----------------|Update() |
// |-----------------------| | observerState= |
// |GetState() | | subject.GetState()|
// | return subject.State()| |--------------------|
// |SetState() | |observer_state |
// |-----------------------|
// |subject_state |
//
// participants
//
// subject
// knows its observers. any number of observer objects may observe
//a subject
// provides an interface for attaching and detaching observer objects
// observer
// defines an updating interface for objects that should be notified
//of changes in a subject
// concrete subject
// stores state of interest to concrete observer objects
// sends a notification to its observers when its state changes
// concrete observer
// maintains a reference to a concrete subject object
// stores state that should stay consistent with the subject's
// implements the observer updating interface to keep its state consistent
//with the subject's
//
// collaborations
//
// concrete subject notifies its observers whenever a change occurs
//that could make its observers' state inconsistent with its own.
// after being informed of a change in the concrete subject, a concrete
//observer object may query the subject for information. concrete observer
//uses this information to reconcile its state with that of the subject.
//
// aConcrete aConcrete another
// Subject Observer ConcreteObserver
// | | |
// | SetState() | |
// | |<-------------------| | |
// | |Notify() | | |
// | |-----------+ | |
// | | | | |
// | |<----------+ | |
// | |Update() | |
// | |------------------->| | |
// | | GetState()| | |
// | |<-------------------| | |
// | |Update() | |
// | |---------------------|--------------->| |
// | | | GetState()| |
// | |<--------------------|----------------| |
// | | |
//
// note how the observer object that initiates the change request postpones
//its update until it gets a notification from the subject. notify is
//not always called by the subject. it can be called by an observer or
//by another kind of object entirely.
//
#include <Mqh\201111_084634.mqh> //push observer
#include <Mqh\201111_084512.mqh> //push subject
#include <Mqh\201111_091110.mqh> //push concrete subject
#include <Mqh\201111_090802.mqh> //push concrete observer
//+------------------------------------------------------------------+
//| client |
//+------------------------------------------------------------------+
void OnStart(void)
{
ConcreteSubject subject;
subject.Attach(new ConcreteObserver(subject));
subject.Attach(new ConcreteObserver(subject));
subject.State("new push state");
subject.Notify();
}
//
// output
//
// subject state set to: new push state
// pushing state to observer 2097152...
// observer 2097152 state updated to: new push state
// pushing state to observer 3145728...
// observer 3145728 state updated to: new push state
//
// consequences
//
// the observer pattern lets you vary subjects and observers independently.
//you can reuse subjects without reusing their observers, and vice versa.
//it lets you add observers without modifying the subject or other observers.
// further benefits and liabilities of the observer pattern include
//the following:
// abstract coupling between subject and observer
// support for broadcast communication
// unexpected updates
//
// implementation
//
// mapping subjects to their observers
// observing more than one subject
// who triggers the update?
// dangling references to deleted subjects
// making sure subject state is self-consistent before notification
// avoiding observer-specific update protocols: the push and pull models
// specifying modifications of interest explicitly
// encapsulating complex update semantics
// combining the subject and observer classes
//
// related patterns
//
// mediator
// singleton
//+------------------------------------------------------------------+
Comments