Δευτέρα 13 Ιουλίου 2020

Memento Pattern (OOP)

There are three classes. But one class has two interfaces. Because we have no interfaces in M2000 we can make two different types, using a class for memento, and a group, handwriting the type as CareTakerMememto. The original Memento class through Store function produce a pointer to copy of this object (any object which inherit Memento), and save it in a private pointer in a Group with type CareTakerMemento. This group has the Restore functions which return the pointer. We can't change the pointer. The Restore function is abstract, technically is a function which raise error, we have to implement in Originator which inherits from Memento.

CareTaker do something with Originator, and after a change get a pointer from the Store function of Originator, because Originator is a memento. The pointer is type of CareTakerMemento, so it is a type which Originator not know. But CareTaker knows exactly what can do, in RollBack.

The example show how we can store the state and restore it, of originator.

\\ memento pattern (OOP)


Class Memento {
Public:
      Function Final Store {
            k->(this)
            Group M {
                  type: CareTakerMemento
            Private:                  
                  a=k
            Public:
                  Function Restore() {
                        =.a
                  }
            }
            ->(M)
      }
      Module Restore {
            Error "abstract"
      }
}
Class Originator as Memento {
Private:      
      state=1
Public:
      module ChangeState {
            .state+=100
      }
      module DisplayState {
            Print "state=";.state
      }
      module Restore(p as *Originator) {
            this=group(p)
      }
}
Class CareTaker {
Private:
      k=pointer()
Public:
      Module DoSomething (&Originator as Originator){
            Originator.ChangeState
            Originator.DisplayState
            .k<=Originator.Store()
            Originator.ChangeState
            Originator.DisplayState
      }
      Module RollBack (&Originator as Originator){
            if .k is type CareTakerMemento then
                  Originator.Restore .k=>Restore()
                  Originator.DisplayState
            End If
      }
}
careTaker=CareTaker()
originator=Originator()
careTaker.DoSomething &originator
careTaker.RollBack  &originator


30 Jan 2021
Using careTaker as pointer to group, so we can use an m item as a pointer to a previous careTaker so we can get a multiple undo function. Also check the remove function which called every time the careTaker get the old value in RollBack. The last remove called when the module exit, so the careTaker get automatic a null pointer before erased as local variable.
Now careTaker has two pointers, one for the state and another for the old careTaker



Class Memento {
Public:
      Function Final Store {
            k->(this)
            Group M {
                  type: CareTakerMemento
            Private:
                  a=k
            Public:
                  Function Restore() {
                        =.a
                  }
            }
            ->(M)
      }
      Module Restore {
            Error "abstract"
      }
}
Class Originator as Memento {
Private:
      state=1
Public:
      module ChangeState {
            .state+=100
      }
      module DisplayState {
            Print "state=";.state
      }
      module Restore(p as *Originator) {
            this=group(p)
      }
}
Class CareTaker {
Private:
      k=pointer()
      m=pointer()
Public:
      Module DoSomething (&Originator as Originator){
            .k<=Originator.Store()
            Originator.ChangeState
            Originator.DisplayState
      }
      Module RollBack (&Originator as Originator){
            if .k is type CareTakerMemento then
                  Originator.Restore .k=>Restore()
                  Originator.DisplayState
                  if not .m is type null then
                        this<=group(.m)
                  end if
            End If
      }
      Remove {
            Print "Remove one"
      }
class:
      module CareTaker() {
      if match("G") then
            read .m as pointer
      end if
      }
}
careTaker->CareTaker()
originator=Originator()
originator.DisplayState
careTaker=>DoSomething &originator
careTaker->CareTaker(careTaker)
careTaker=>DoSomething &originator
careTaker->CareTaker(careTaker)
careTaker=>DoSomething &originator
careTaker=>RollBack &originator
careTaker=>RollBack &originator
careTaker=>RollBack &originator


Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.