实现可撤消命令 - Java
我目前正在编写一个小型文本编辑器(学校项目),并且在寻找一种良好且干净的方法来管理可撤消命令时遇到了一些麻烦。
(这不是一个代码审查问题,因为它不仅涉及改进。如果我希望我的应用程序按我希望的方式工作,我需要更改我的代码)
这是我的应用程序的工作原理:我有一个具体的主题,它保存了缓冲区实际上是一个字符数组列表。每当这个数组列表被修改(插入、剪切、粘贴...)时,主体就会更新观察者 - 目前仅包含一个 gui - (MVC 模式)。
到目前为止,我所做的撤消和重做是保存缓冲区的整个状态(通过备忘录),这工作正常,但是:
- 显然可以改进。
- 不适用于我需要实现的新功能(记录用户操作,以便他可以随时播放它们)
我不知道如何保存命令而不是缓冲区,以及这是否是好方法去。
下面是程序的一些块(用于插入命令):
"GUI".java
...
class KeyboardListener extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
...
commandManager.executeCommandInsert(caretStart, caretStop, e.getKeyChar());
...
}
...
}
CommandManager.java
...
public void executeCommandInsert(int start, int end, char character) {
addMementoUndo();
commandInsert.setCarets(start, end);
commandInsert.setChar(character);
commandInsert.execute();
}
public void addMementoUndo()
{
TextConcrete text = TextConcrete.getInstance();
this.commandsUndo.add(0, text.createMemento());
if(recordMode){
this.recordings.add(text.createMemento());
}
}
...
CommandInsert.java
...
public void execute(){
TextConcrete text = TextConcrete.getInstance();
text.insert(this.start, this.end, this.character);
}
...
TextConcrete。 java
...
public void insert(int start, int end, char character){
//inserting in ArrayList
}
public CommandUndoable createMemento(){
CommandUndoable mem = new CommandUndoable();
mem.setState(getState());
return mem;
}
public String getState(){
StringBuilder temp = new StringBuilder();
for(int idx = 0; idx < this.state.size(); idx++){
temp.append(this.state.get(idx));
}
return temp.toString();
}
...
CommandUndoable 只是保存缓冲区状态的备忘录,然后保存在 CareTaker(CommandManager)中的备忘录列表中。
任何帮助将不胜感激。
I'm currently programming a little text editor (project for school) and I'm having some troubles finding a good and clean way to manage the undoable commands.
(It is not a code review question as it's not only about improvement. I need to change my code if I want my application to work as I want it to)
Here's how my application works: I have a concrete subject that holds the buffer that is actually an arraylist of characters. Whenever this arraylist is modified (insertion, cut, paste...), the subject updates the observers - which consist in only one gui for the moment - (MVC pattern).
What I was doing until now for the undo and redo was saving the whole state of the buffer (through a memento), which is working fine but:
- could obviously be improved.
- is not working for the new feature that I need to implement (recording user actions so he can play them back whenever he wants to)
I can't figure out how to save the commands instead of the buffer, and if it is the good way to go.
Here's some chunks of the program (for the insert command):
"GUI".java
...
class KeyboardListener extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
...
commandManager.executeCommandInsert(caretStart, caretStop, e.getKeyChar());
...
}
...
}
CommandManager.java
...
public void executeCommandInsert(int start, int end, char character) {
addMementoUndo();
commandInsert.setCarets(start, end);
commandInsert.setChar(character);
commandInsert.execute();
}
public void addMementoUndo()
{
TextConcrete text = TextConcrete.getInstance();
this.commandsUndo.add(0, text.createMemento());
if(recordMode){
this.recordings.add(text.createMemento());
}
}
...
CommandInsert.java
...
public void execute(){
TextConcrete text = TextConcrete.getInstance();
text.insert(this.start, this.end, this.character);
}
...
TextConcrete.java
...
public void insert(int start, int end, char character){
//inserting in ArrayList
}
public CommandUndoable createMemento(){
CommandUndoable mem = new CommandUndoable();
mem.setState(getState());
return mem;
}
public String getState(){
StringBuilder temp = new StringBuilder();
for(int idx = 0; idx < this.state.size(); idx++){
temp.append(this.state.get(idx));
}
return temp.toString();
}
...
The CommandUndoable is just the memento that save the state of the buffer and then is saved in a list of memento in the CareTaker (CommandManager).
Any help would really be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以创建一个命令可以实现的可撤消接口,例如:
其中Editor是编辑器的模型,您可以在其中插入文本、从中删除文本或与其他编辑器一起操作命令。实现该接口的命令只需要知道如何“执行”和“撤消”本身,因此您不需要在每一步存储文本缓冲区的副本,只需存储文本缓冲区的列表命令。
You could create a Undoable interface that commands can implement such as:
where Editor is the model of your editor that you can insert text into, remove text from, or manipulate with other commands. A command implementing the interface only needs to know how to 'do' and 'undo' itself, so you do not need to store a copy of the text buffer at each step, just store a List of the commands.
我更愿意定义两个接口,但在它们的方法中没有任何参数
......对于撤消操作:
我认为,这更灵活,因为您的应用程序中可能有一些不可撤消的交互。 (就像保存或加载文件一样)
要实现这样的
UndoableCommand
,只需编写类似的代码。execute
和undo
的处理可以是也通过 CommandManager 完成。I would prefer to define two interfaces, but without any arguments in their methods
... and for Undo Actions:
I think, this is more flexible, because you may have some interactions in your application that are not Undoable. (Like saving or loading a file)
To implement such a
UndoableCommand
just write somethink like that..The handling of
execute
andundo
, can be done via aCommandManager
as well.