Памятка в Яве.Изменчивое состояние - PullRequest
0 голосов
/ 13 июня 2018

Я пытаюсь понять Шаблон Памяти.Для этого я пытаюсь реализовать функцию отмены.Проблема в том, что когда я сохраняю старое состояние отправителя в очереди и запускаю другую функцию, состояние сохранения изменяется на текущее состояние.Мне действительно нужна помощь, чтобы понять, что я делаю неправильно.Как я могу сделать вектор неизменным.

Это класс памяти.

package memento;

public class Memento
{
    private final boolean[] vectorState;

    public Memento(boolean[] vector) {vectorState = vector;}

    boolean[] getMemento() { return vectorState;}

}

Инициатору просто нужно сместить вектор логического значения влево.(TRUE, FALSE, FALSE) сдвиг влево возвращает: (FALSE, FALSE, TRUE).Это реализация.

package memento;

public class ShilftLeftOriginator
{
    private boolean[] vector;

    public ShilftLeftOriginator(boolean[] vector) {this.vector = vector;}

    public void execute()
    {
        final boolean firstValue = this.vector[0];
        for (int i = 1; i < this.vector.length; i++) {
            this.vector[i - 1] = this.vector[i];
        }
        this.vector[vector.length - 1] = firstValue;
    }


    public Memento saveToMemento() {return new Memento(vector);}

}

И смотритель:

package memento;

import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;


public final class BooleanVector {
    private boolean[] vector;
    private Deque<Memento> mementoList = new LinkedList<>();

    public BooleanVector(boolean[] inputValues) {
        this.vector = inputValues;
    }


    @Override
    public boolean equals(Object obj) 
    {
        if (obj == null) return false;
        if (!(obj instanceof BooleanVector)) return false;
        BooleanVector otherVector = (BooleanVector) obj;
        return Arrays.equals(this.vector, otherVector.vector);
    }

    public void shiftLeft() 
    {
        ShilftLeftOriginator shiftLeft = new ShilftLeftOriginator(vector);
        mementoList.add(shiftLeft.saveToMemento());
        shiftLeft.execute(); // This is my Problem. After execute ist call the value(vector) in mementoList changes             
    }

    public void undo(){ this.vector =  mementoList.pop().getMemento();}

}

А теперь тестовый класс и ошибка, которую я получаю.

package memento;

public class Main {

    public static void main(String[] args) {
        boolean[] inputValues = { false, true, false };
        BooleanVector vector = new BooleanVector(inputValues);

        vector.shiftLeft();

        boolean[] expectedValues = new boolean[] { true, false, false };
        BooleanVector expectedVector = new BooleanVector(expectedValues);

        if (!vector.equals(expectedVector)) {
            throw new IllegalStateException(vector.toString());
        } else {
            System.out.println("shiftleft working");
        }

        vector.undo();

        expectedValues = new boolean[] { false, true, false };
        expectedVector = new BooleanVector(expectedValues);

        if (!vector.equals(expectedVector)) {
            throw new IllegalStateException(vector.toString());
        } else {
            System.out.println("undo working");
        }

    }

}

консольный вывод:

shiftleft working
Exception in thread "main" java.lang.IllegalStateException: [true, false, false]
    at memento.Main.main(Main.java:26)

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

Я могу дать вам немного более расширяемое решение:

Класс оригинатора: абстрактный имплементаци значения T держатель

public abstract class Originator<T> {

    private T value;
    private final CareTaker<T> careTaker;

    protected Originator(T value, CareTaker<T> careTaker) {
        this.value = value;
        this.careTaker = careTaker;
    }

    public final T getValue() {
        return value;
    }

    protected final void setValue(T value) {
        careTaker.add(this.value);
        this.value = value;
    }

    public final void undo() {
        if (!careTaker.isEmpty())
            value = careTaker.remove();
    }

}

класс BooleanVector: конкретная реализация, содержащая boolean[]

public final class BooleanVector extends Originator<boolean[]> {

    public BooleanVector(boolean[] obj) {
        super(obj, new CareTaker<>());
    }

    public void leftShift() {
        if (getValue() == null || getValue().length == 0)
            return;

        boolean[] arr = new boolean[getValue().length];
        boolean tmp = arr[0];
        System.arraycopy(getValue(), 1, arr, 0, getValue().length - 1);
        arr[arr.length - 1] = tmp;
        setValue(arr);
    }

}

класс CareTaker: реализация изменения значенийистория - память

public final class CareTaker<T> {

    private final Deque<Item<T>> stack = new LinkedList<>();

    public void add(T value) {
        stack.push(new Item<>(value));
    }

    public T remove() {
        return stack.pop().data;
    }

    public boolean isEmpty() {
        return stack.isEmpty();
    }

    private static final class Item<T> {

        private final T data;

        public Item(T data) {
            this.data = data;
        }
    }
}

Демо:

public static void main(String[] args) {

    BooleanVector originator = new BooleanVector(new boolean[] { false, true, false });
    System.out.println(Arrays.toString(originator.getValue()));
    System.out.println("---");
    originator.leftShift();
    System.out.println(Arrays.toString(originator.getValue()));
    originator.undo();
    System.out.println(Arrays.toString(originator.getValue()));
}

Выход:

[false, true, false]
---
[true, false, false]
[false, true, false]
0 голосов
/ 13 июня 2018

Проблема в том, что вы всегда манипулируете одним и тем же массивом.Поэтому, если вы сдвигаете влево, вы также сдвигаете влево массив, который вы сохранили в объекте Memento, потому что это все тот же массив.

Чтобы решить его, сделайте копию массива в конструкторе Memento объект:

public Memento(boolean[] vector) {
    vectorState = Arrays.copyOf(vector, vector.length);
}

Помимо этого, у вас, кажется, смешались ваши классы.BooleanVector и ShilftLeftOriginator - инициатор, а Main - смотритель.

...