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);
}
除此之外,您的 类 似乎搞混了。 BooleanVector
和 ShilftLeftOriginator
是发起人,而 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]
我正在尝试理解纪念品模式。为此,我正在尝试实现撤消功能。问题是,每当我在队列中保存发起者的旧状态和 运行 一个不同的函数时,保存状态就会更改为当前状态。我真的需要帮助来理解我做错了什么。我怎样才能使向量不可变。
这是纪念品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);
}
除此之外,您的 类 似乎搞混了。 BooleanVector
和 ShilftLeftOriginator
是发起人,而 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]