java 中的纪念品。可变状态

Memento in java. Mutable state

我正在尝试理解纪念品模式。为此,我正在尝试实现撤消功能。问题是,每当我在队列中保存发起者的旧状态和 运行 一个不同的函数时,保存状态就会更改为当前状态。我真的需要帮助来理解我做错了什么。我怎样才能使向量不可变。

这是纪念品class。

package memento;

public class Memento
{
    private final boolean[] vectorState;

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

    boolean[] getMemento() { return vectorState;}

}

发起者只需要将一个布尔值向量左移。 (TRUE,FALSE,FALSE) 左移 returns: (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();}

}

现在是测试 class 和我收到的错误。

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)

问题是您总是在操作同一个数组。所以如果你向左移动,你也会向左移动你存储在 Memento 对象中的数组,因为它们都是同一个数组。

为了解决它,在 Memento 对象的构造函数中复制数组:

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

除此之外,您的 类 似乎搞混了。 BooleanVectorShilftLeftOriginator 是发起人,而 Main 是看守人。

我可以给你一个更可扩展的解决方案:

class 发起人: 价值的抽象实现 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();
    }

}

class 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);
    }

}

class 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]