Java中的Memento设计模式

时间:2018-03-12 16:01:24

标签: java reference immutability memento

我正在实现一个Java应用程序,它通过简单的命令生成svg代码,例如" add_circle 12 20 5"。有四种形状,如Rectangle,Circle,......它们的每一类都实现了一个名为Component的接口。常见功能包括:translate(dx,dy)flip_vertical(axis)flip_horizontal(axis)write(output)

还有一个名为Group的类,它也实现了组件接口。它唯一的字段是ArrayList<Component> groupOfComponents,用于在其中存储组件。如果调用此类的转换函数,它将调用数组中每个组件的转换函数。

应用程序的其他部分生成了svg,但它现在无关紧要。长话短说,我想做一个撤销机制。要做到这一点而不破坏封装,我将不得不使用Memento设计模式。

备忘录

我已经为它(Memento类)编写了一个名为GroupState的新类。它是一个存储先前状态的类,以便以后可以恢复。由于我需要从Group对象存储的唯一信息是它的数组,因此它存储了一个ArrayList。

public class GroupState  {
    private final ArrayList<Component> state;
    public GroupState(ArrayList<Component> state) {
        this.state = state;
    }
    public ArrayList<Component> getState() {
        return state;
    }
}

始发

发起人是Group类,我必须添加2个新方法:saverestore。这些方法旨在保存Goup的状态并恢复它。

public class Group implements Component{
    public GroupState save(){
        return new GroupState(groupOfComponents);
    }
    public void restore(GroupState state) {
        groupOfComponents = state.getState();
    }
    private ArrayList<Component> groupOfComponents = new ArrayList<>();
    /** .
        .
        other parts of the class
        .
    */
}

看守

看护人管理整个撤销过程。这是我班级的一部分无关紧要,所以我要编写一些代码来说明我想如何使用整个撤销机制。

Group group = new Group();

Circle circle = new Circle(1,2,3);

group.addComponent(circle);

Stack<GroupState> savedStates = new Stack<>();

savedStates.push(group.save());

group.flipHorizontal(100);

group.restore(savedStates.pop());

我期望发生的事情如下:

  1. 创建一个空组
  2. 创建一个带有一些参数的圆圈
  3. 将圆圈添加到组中(将圆圈添加到组类的groupOfComponents数组中)
  4. 创建堆栈以存储状态
  5. 将组对象的状态保存到堆栈
  6. 对组对象进行更改(例如翻转)
  7. 撤消上次更改(从状态堆栈恢复)
  8. 问题

    而不是预测的行为,在最后一步是这里发生的事情:

    1. 没有
    2. 我开始调试整个事情,并注意到,当我使用该翻转方法更改组对象时,GroupState对象的字段state也会发生变化。我不知道为什么。首先,state字段是最终的。其次,我知道在引用类型中,引用已经通过但是不变性,为什么第6步也改变了GtoupState的字段呢?如何使GroupState从传递的数组中复制数据?谢谢你的帮助。

0 个答案:

没有答案