mercredi 10 mai 2017

Memento Design Pattern - Who should provided Save/Undo Functionality

I am trying to understand Memento Design Pattern from various links. As per my understanding, there are 3 main participants in Memento Design Pattern - Originator, Memento and CareTaker. At high level, I understand the purpose of these classes and created a sample program -

Originator class and Memento Inner Class Memento is created as inner class so that only Originator knows about it. CareTaker will not be able to access it.

public class CalculatorOriginator {

    private int firstNumber;

    private int secondNumber;

    private int total;

    public int getTotal() {
        total = firstNumber + secondNumber;
        return total;
    }

    public int getFirstNumber() {
        return firstNumber;
    }

    public void setFirstNumber(int firstNumber) {
        this.firstNumber = firstNumber;
    }

    public int getSecondNumber() {
        return secondNumber;
    }

    public void setSecondNumber(int secondNumber) {
        this.secondNumber = secondNumber;
    }

    public CalculatorMemento save() {
        return new CalculatorMemento(firstNumber, secondNumber);
    }

    public void restore(Object obj) {
        CalculatorMemento calculatorMemento = (CalculatorMemento) obj;
        this.firstNumber = calculatorMemento.getFirstNumber();
        this.secondNumber = calculatorMemento.getSecondNumber();
    }

    private class CalculatorMemento {

        private int firstNumber;

        private int secondNumber;

        public CalculatorMemento(int firstNumber, int secondNumber) {
            this.firstNumber = firstNumber;
            this.secondNumber = secondNumber;
        }

        public int getFirstNumber() {
            return firstNumber;
        }

        public int getSecondNumber() {
            return secondNumber;
        }
    }
}

CareTaker Class

public class CalculatorCareTaker {

    private static final String IMAGE_PREFIX = "Image-";
    private Map<Integer, Object> stateMap = new HashMap<>();

    private Integer currentStateCount = 0;

    private CalculatorOriginator calculatorOriginator;

    public CalculatorCareTaker(CalculatorOriginator calculatorOriginator) {
        this.calculatorOriginator = calculatorOriginator;
    }

    public String save() {
        Object state = calculatorOriginator.save();
        stateMap.put(++currentStateCount, state);
        return IMAGE_PREFIX + currentStateCount;
    }

    public void restore(String state) {
        String stateCountStr = state.replace(IMAGE_PREFIX, "");
        Integer stateCountInt = Integer.valueOf(stateCountStr);
        Object obj = stateMap.get(stateCountInt);
        if (obj == null) {
            throw new IllegalArgumentException("Input state is not valid state");
        }
        calculatorOriginator.restore(obj);
    }

    public void restoreToLastSavedPoint() {
        if (currentStateCount == 0) {
            throw new UnsupportedOperationException("No last saved point exist");
        }
        Object obj = stateMap.get(currentStateCount);
        calculatorOriginator.restore(obj);
    }
}

Now I have following doubts -

  1. Is above sample code showing correct way of implementing Memento Design Pattern ?

  2. CareTaker and Originator both classes are exposing save() and restore() methods which is not good I think as client program may call Originator methods and then state will not be maintained. So, who should actually provide these methods and how I can prevent another class for not exposing such methods ?

  3. In some of the link, Originator stores CareTaker instance and in some link, CareTaker storesOriginator instance. Currently, in my code, CareTaker uses Originator instance. So, is this correct way ? In some of the stackoverflow answers, I found that both approaches are fine. In such case, what is the recommended approach or pros/cons of these 2 approaches.

Aucun commentaire:

Enregistrer un commentaire