撤销与反撤销 功能实现
来源:互联网 发布:付费软件大全 编辑:程序博客网 时间:2024/06/02 16:23
你一定经常看见类似下面的图标:
它们就表示“撤销”与“反撤销”。在程序中,这种功能通常是使用Command模式实现的,本文也不例外。首先抽象定义Command,使用ICommand接口:
可撤销的命令也是一种命令,所以从ICommand继承:
为了实现撤销功能,我们需要一个堆栈来记录所有已执行的可撤销命令,为了实现反撤销的功能,同样,我们也需要一个堆栈来记录所有已撤销的命令。这个职责是由ICommandManager接口提供:
现在,我们来详细分析一下,撤销命令堆栈和反撤销命令堆栈在何时Push命令对象、又在何时Pop命令对象:
(1)当执行完任何一个command后,reverseUndo堆栈清空
(2)当执行完一个不可撤销的command后,undo堆栈清空
(3)当执行完一个可撤销的command后,将其压入undo堆栈
(4)当撤销一个command后,将其转移到reverseUndo堆栈
基于此,我们就可以实现ICommandManager:
本文介绍的撤销与反撤销功能是与应用无关的,所以可以在不同的应用中复用,你只需要根据你自己的应用需求来实现对应的ICommand接口和IBackableCommand接口就可以立即使用撤销与反撤销功能了。
它们就表示“撤销”与“反撤销”。在程序中,这种功能通常是使用Command模式实现的,本文也不例外。首先抽象定义Command,使用ICommand接口:
public interface ICommand
{
void Excute() ;
}
Excute表示执行该ICommand引用的目标的所包含的动作(或动作序列)。{
void Excute() ;
}
可撤销的命令也是一种命令,所以从ICommand继承:
public interface IBackableCommand :ICommand
{
void Undo() ;
}
一个可撤销的命令表明调用其Excute方法后,再调用其Undo方法可以使被操作的对象回复到之前的状态。{
void Undo() ;
}
为了实现撤销功能,我们需要一个堆栈来记录所有已执行的可撤销命令,为了实现反撤销的功能,同样,我们也需要一个堆栈来记录所有已撤销的命令。这个职责是由ICommandManager接口提供:
public interface ICommandManager
{
void ExcuteCommand(ICommand command) ;
void Undo() ;
void ReverseUndo() ;//反撤销
//以下事件可用于控制撤销与反撤销图标的启用
event CbSimpleBool UndoStateChanged ; //bool参数表明当前是否有可撤销的操作
event CbSimpleBool ReverseUndoStateChanged ; //bool参数表明当前是否有可反撤销的操作
}
{
void ExcuteCommand(ICommand command) ;
void Undo() ;
void ReverseUndo() ;//反撤销
//以下事件可用于控制撤销与反撤销图标的启用
event CbSimpleBool UndoStateChanged ; //bool参数表明当前是否有可撤销的操作
event CbSimpleBool ReverseUndoStateChanged ; //bool参数表明当前是否有可反撤销的操作
}
现在,我们来详细分析一下,撤销命令堆栈和反撤销命令堆栈在何时Push命令对象、又在何时Pop命令对象:
(1)当执行完任何一个command后,reverseUndo堆栈清空
(2)当执行完一个不可撤销的command后,undo堆栈清空
(3)当执行完一个可撤销的command后,将其压入undo堆栈
(4)当撤销一个command后,将其转移到reverseUndo堆栈
基于此,我们就可以实现ICommandManager:
public class CommandManager :ICommandManager
{
private Stack undoStack = new Stack() ;
private Stack reverseStack = new Stack() ;
public event CbSimpleBool UndoStateChanged ;
public event CbSimpleBool ReverseUndoStateChanged ;
public CommandManager()
{
this.UndoStateChanged += new CbSimpleBool(CommandManager_UndoStateChanged);
this.ReverseUndoStateChanged += new CbSimpleBool(CommandManager_UndoStateChanged) ;
}
private void CommandManager_UndoStateChanged(bool val)
{
}
#region ICommandManager 成员
public void ExcuteCommand(ICommand command)
{
command.Excute() ;
this.reverseStack.Clear() ;
if(command is IBackableCommand)
{
this.undoStack.Push(command) ;
}
else
{
this.undoStack.Clear() ;
}
this.UndoStateChanged(this.undoStack.Count > 0) ;
}
public void Undo()
{
IBackableCommand command = (IBackableCommand)this.undoStack.Pop() ;
if(command == null)
{
return ;
}
command.Undo() ;
this.reverseStack.Push(command) ;
this.ReverseUndoStateChanged(this.reverseStack.Count > 0) ;
}
public void ReverseUndo()
{
IBackableCommand command = (IBackableCommand)this.reverseStack.Pop() ;
if(command == null)
{
return ;
}
command.Excute() ;
this.undoStack.Push(command) ;
this.UndoStateChanged(this.undoStack.Count > 0) ;
this.ReverseUndoStateChanged(this.reverseStack.Count > 0) ;
}
#endregion
}
{
private Stack undoStack = new Stack() ;
private Stack reverseStack = new Stack() ;
public event CbSimpleBool UndoStateChanged ;
public event CbSimpleBool ReverseUndoStateChanged ;
public CommandManager()
{
this.UndoStateChanged += new CbSimpleBool(CommandManager_UndoStateChanged);
this.ReverseUndoStateChanged += new CbSimpleBool(CommandManager_UndoStateChanged) ;
}
private void CommandManager_UndoStateChanged(bool val)
{
}
#region ICommandManager 成员
public void ExcuteCommand(ICommand command)
{
command.Excute() ;
this.reverseStack.Clear() ;
if(command is IBackableCommand)
{
this.undoStack.Push(command) ;
}
else
{
this.undoStack.Clear() ;
}
this.UndoStateChanged(this.undoStack.Count > 0) ;
}
public void Undo()
{
IBackableCommand command = (IBackableCommand)this.undoStack.Pop() ;
if(command == null)
{
return ;
}
command.Undo() ;
this.reverseStack.Push(command) ;
this.ReverseUndoStateChanged(this.reverseStack.Count > 0) ;
}
public void ReverseUndo()
{
IBackableCommand command = (IBackableCommand)this.reverseStack.Pop() ;
if(command == null)
{
return ;
}
command.Excute() ;
this.undoStack.Push(command) ;
this.UndoStateChanged(this.undoStack.Count > 0) ;
this.ReverseUndoStateChanged(this.reverseStack.Count > 0) ;
}
#endregion
}
本文介绍的撤销与反撤销功能是与应用无关的,所以可以在不同的应用中复用,你只需要根据你自己的应用需求来实现对应的ICommand接口和IBackableCommand接口就可以立即使用撤销与反撤销功能了。
- 撤销与反撤销 功能实现
- 撤销与反撤销 功能实现
- Android画板开发(三) 撤销反撤销功能实现
- vim撤销undo与反撤销redo
- vim撤销undo与反撤销redo
- 涂鸦撤销与重做的功能实现
- 实现撤销功能的思想
- js实现撤销恢复功能
- easyui 实现复制与撤销
- HBuilder反撤销快捷键
- 撤销功能的实现----备忘录模式
- ArcEngine实现撤销和重置功能
- android画图并实现撤销功能
- View实现涂鸦、撤销以及重做功能
- iOS UITextView 首行缩进 撤销输入 反撤销输入的实现
- Linux vi 撤销与取消撤销
- [Vim]撤销与重做
- VIM 撤销与恢复
- 我的留学生活[7]-Chinese MEMI!?
- 序列化part1
- 好的编码风格和不好的
- gdb输出重定向
- 换个角度看SOA
- 撤销与反撤销 功能实现
- MultiGencreator
- POI 解析excel时sheet的实际行数,数字问题
- .Net下采用GET/POST/SOAP方式动态调用WebService的简易灵活方法(C#)
- Linux netfilter源码分析(3)
- CUDA学习笔记之程序优化
- 资产从AP传送到FA的流程介绍
- 常见的内存的分配错误及其对策
- 影响你未来发展的十二大著名法则