//+------------------------------------------------------------------+ //| 201104_114239.mq5 | //| 2019-2020, dimitri pecheritsa | //| 792112@gmail.com | //+------------------------------------------------------------------+ // from: design patterns: elements of reusable object-oriented software // by gof: erich gamma, richard helm, ralph johnson, john vlissides // published in 1994 //+------------------------------------------------------------------+ //| memento - behavioral design pattern | //+------------------------------------------------------------------+ // without violating encapsulation, capture and externalize an object's //internal state so that the object can be restored to this state later //+------------------------------------------------------------------+ //| applicability | //+------------------------------------------------------------------+ // a snapshot of (some portion of) an object's state must be saved so //that it can be restored to that state later, and // a direct interface to obtaining the state would expose implementation //details and break the object's encapsulation //+------------------------------------------------------------------+ //| structure | //+------------------------------------------------------------------+ // memento // | Originator |- - ->| Memento |<-------o|Caretaker| // |--------------------------| |----------| // |SetMemento(Memento m) | |GetState()| // | state=m.GetState() | |SetState()| // |CreateMemento() | |----------| // | return new Memento(state)| |state | // |--------------------------| // |state | // //+------------------------------------------------------------------+ //| participants | //+------------------------------------------------------------------+ // memento // stores internal state of the originator object. the memento may //store as much or as little of the originator's internal state as necessary //at its originator's discretion // protects against access by objects other than the originator. //mementos have effectively two interfaces. caretaker sees a narrow interface //to the memento — it can only pass the memento to other objects. originator, //in contrast, sees a wide interface, one that lets it access all the data //necessary to restore itself to its previous state. ideally, only the //originator that produced the memento would be permitted to access the //memento's internal state // originator // creates a memento containing a snapshot of its current internal state // uses the memento to restore its internal state // caretaker // is responsible for the memento's safekeeping // never operates on or examines the contents of a memento //+------------------------------------------------------------------+ //| collaborations | //+------------------------------------------------------------------+ #include <Mqh201104_114823.mqh> //memento #include <Mqh201104_115143.mqh> //originator #include <Mqh201104_115621.mqh> //caretaker // a caretaker requests a memento from an originator, holds it for a //time, and passes it back to the originator: // // aCaretaker anOriginator aMemento // | | | // | |CreateMemento() | // | |--------------------->| |new Memento | // | | | |- - - - - - - - - - ->| | // | | | |SetState() | // | | | |--------------------->| | // | | | // / / / // / / / // | | | // | |SetMemento() | | // | |--------------------->| |GetState() | // | | | |--------------------->| | // | | | // // sometimes the caretaker won't pass the memento back to the originator, //because the originator might never need to revert to an earlier state // mementos are passive. only the originator that created a memento will //assign or retrieve its state //--- void OnStart() { Originator originator; Caretaker caretaker; //--- originator.State("on"); caretaker.memento=originator.CreateMemento(); originator.State("off"); originator.SetMemento(caretaker.memento); } //+------------------------------------------------------------------+ //| output | //+------------------------------------------------------------------+ // changing originator state to on // creating memento with current state on // changing originator state to off // restoring originator state from memento to on //+------------------------------------------------------------------+ //| consequences | //+------------------------------------------------------------------+ // preserving encapsulation boundaries // it simplifies originator // using mementos might be expensive // defining narrow and wide interfaces // hidden costs in caring for mementos //+------------------------------------------------------------------+ //| implementation | //+------------------------------------------------------------------+ // language support // storing incremental changes //+------------------------------------------------------------------+ //| related patterns | //+------------------------------------------------------------------+ // command: commands can use mementos to maintain state for undoable operations // iterator: mementos can be used for iteration as described earlier //+------------------------------------------------------------------+