Java Memorandum Mode

Posted by mdowling on Wed, 17 Jul 2019 23:05:45 +0200

Memorandum mode, also known as Snapshot Pattern or Token pattern, is the behavior pattern of objects.

A memo object is an object that stores snapshots of the internal state of another object. The purpose of the memo mode is to capture and externalize the state of an object without destroying the encapsulation, so that it can be restored to the stored state at the appropriate time in the future. Memorandum mode is often used in conjunction with command mode and iteration sub-mode.

Structure of Memorandum Model

The structure of the memorandum pattern is shown below.

The memorandum model involves three roles: the Memento role, the Originator role and the Caretaker role.

Memento role

The memorandum roles also have the following responsibilities:

1. Store the internal state of the Originator object. A memorandum can determine how many internal states of the Originator object are stored based on the judgment of the initiator object.
 
2. A memo can protect its content from being read by any object other than the Originator object.

The MOU has two equivalent interfaces:

  • Narrow interface: The Caretaker object (and any other object except the initiator object) sees the narrow interface of the memo, which only allows it to pass the memo object to other objects.

  • Wide interface: Contrary to the narrow interface seen by the responsible object, the initiator object can see a wide interface, which allows it to read all the data in order to restore the internal state of the initiator object.

Originator role

The Originator role has the following responsibilities:

  1. Create a memo object with the current internal state.

  2. Memory objects are used to store their internal state.

Caretaker role

The Caretaker role has the following responsibilities:

  1. Responsible for saving memo objects.

  2. Do not check the contents of the memo object.

Implementation of "White Box" Memorandum Model

A memo role provides an interface to any object, that is, a wide interface, and the state stored within the memo role is exposed to all objects. So this implementation is also called "white box implementation".

The "white box" implementation stores the status of the sponsor's role in a place that everyone can see, thus destroying the encapsulation. But programmer self-discipline can also achieve most of the intentions of the pattern to a certain extent. So white box implementation is still meaningful.

Originator role

/**
 * Created by yangtianrui on 17-3-18.
 * Initiator role
 */
public class Originator {

    // Simulate a state
    private String mState;

    public Originator(String state) {
        mState = state;
    }


    public void setState(String state) {
        mState = state;
    }

    public Memento createMemento() {
        return new Memento(mState);
    }

    // Output status
    public void printState() {
        System.out.println(mState);
    }
}

Memento role

/**
 * Created by yangtianrui on 17-3-18.
 * A memo object that stores the state of Originator
 */
public class Memento {

    private String mState;

    public String getState() {
        return mState;
    }

    public void setState(String state) {
        mState = state;
    }

    public Memento(String state) {
        mState = state;
    }
}

CareTaker role

/**
 * Created by yangtianrui on 17-3-18.
 * The person in charge role, the person in charge saves the state of the object
 */
public class CareTaker {

    private Memento mMemento;


    public CareTaker(Memento memento) {
        mMemento = memento;
    }

    /**
     * Get status
     */
    public String retrieveState() {
        return mMemento.getState();
    }

    /**
     * In-state
     */
    public void saveState(Memento memento) {
        mMemento = memento;
    }
}

Test class

public class Main {

    public static void main(String[] args) {
        // Initialization state
        final Originator originator = new Originator("Initial state.");

        originator.printState();
        // Use CareTaker to save state

        final CareTaker careTaker = new CareTaker(originator.createMemento());

        // modify state
        originator.setState("Modify this state.");

        // Modified state of output
        originator.printState();

        // Use Memento to restore state
        originator.setState(careTaker.retrieveState());

        // Output recovery status
        originator.printState();

        /*Result
          Initial state.
          Modify this state.
          Initial state.
         */
    }
}

Implementation of "Black Box" Memorandum Model

In the Java language, the way to implement dual interfaces is to design the memo role class as an internal member class of the initiator role class.

Setting Memento as an internal class of Originator class encapsulates the Memento object in Originator.
An identification interface, MementoIF, is provided externally to Caretaker and other objects.

Thus, the Originator class sees all the interfaces of Menmento, while Caretaker and other objects see only the interfaces exposed by the identification interface MementoIF.

Design of Wide and Narrow Interface

IMemento

Provide only a simple interface to the outside world

/**
 * Created by yangtianrui on 17-3-18.
 * Memorandum Interface Provided Externally
 */
public interface IMemento {
}

Originator role, encapsulating memos through internal classes

public class Originator {

    // Simulate saved state
    private String mState;

    public Originator(String state) {
        mState = state;
    }

    public void setState(String state) {
        mState = state;
    }

    public void printState() {
        System.out.println(mState);
    }


    // Create a Memorandum Save Object
    public IMemento createMemento() {
        // Save objects
        return new OriginMemento(mState);
    }

    // Recovery from the Memorandum
    public void restoreMemento(IMemento memento) {
        if (memento instanceof OriginMemento) {
            mState = ((OriginMemento) memento).getState();
        }
    }


    /**
     * Encapsulation of object state through internal classes
     */
    private class OriginMemento implements IMemento {
        private String mState;

        public OriginMemento(String state) {
            mState = state;
        }

        public String getState() {
            return mState;
        }

        public void setState(String state) {
            mState = state;
        }
    }
}

CareTaker role, managing memos

public class CareTaker {

    // External performance is only an interface, reflecting the encapsulation.
    private IMemento mMemento;

    public void setMemento(IMemento memento) {
        mMemento = memento;
    }


    public IMemento getMemento() {
        return mMemento;
    }


}

Test class

public class Main {

    public static void main(String[] args) {

        // Initial state
        final Originator originator = new Originator("Initial state.");
        originator.printState();

        // Storage status to memo
        final CareTaker careTaker = new CareTaker();
        careTaker.setMemento(originator.createMemento());

        // Change status
        originator.setState("Modified state.");
        originator.printState();

        // Recovery status
        originator.restoreMemento(careTaker.getMemento());
        originator.printState();


        /*
          Result
         *Initial state.
         *Modified state.
         *Initial state.
         */
    }
}

Code download: https://github.com/yangtianrui95/Design-Patterns

Topics: snapshot Java github