文本编辑器中,如何设计 撤销/重复栈
来源:互联网 发布:学java看什么书 编辑:程序博客网 时间:2024/04/30 10:24
关键在于两点:栈 和 多态。
如何设计:
很容易想到使用栈来保持那些已经被执行的操作,当要撤销上一步操作时,只需要取出栈顶元素并执行该元素所对应的操作便可。
接踵而至的一个问题是: 栈中元素类型是什么? 由于我们需要保存各种不同的文本编辑操作,要将它们统一地保存在一起,很自然地,我们应该让这些操作有着统一的父类, 我们栈中元素的类型是该父类类型就可以了.
我们这里设计了一个接口,所有的可撤销/重复的操作都应该继承该接口:
/// <summary>
/// 可撤销重复操作接口。
/// 所有的可重复可撤销的操作都应该继承这个接口。
/// </summary>
interface IUndoableOperate
{
void Undo();
void Redo();
void Execute();
}
比如我们有一个操作Operate1,它继承了IUndoableOperate接口
/// <summary>
/// 操作1
/// </summary>
class Operate1 : IUndoableOperate
{
#region IUndoableOperate 成员
/// <summary>
/// 撤销该操作时执行
/// </summary>
public void Undo()
{
Console.WriteLine("undo operate1");
}
/// <summary>
/// 重复该操作时执行
/// </summary>
public void Redo()
{
Console.WriteLine("do operate1");
}
/// <summary>
/// 执行操作1
/// </summary>
public void Execute()
{
this.Redo();
}
#endregion
}
其它任何与Operate1类似的操作都可以放到撤销栈中,以便以后撤销。
栈中元素都是IUndoableOperate类型,那么当我们取出栈顶元素并调用其Execute()函数时,其能被正确的执行吗?答案是肯定的,这利用了多态。
现在我们可以设计一个管理器来对栈进行管理,它将记录那些被执行或被撤销的操作,并提供方法允许你对已经执行过的操作进行撤销、已经撤销的操作进行重复。
/// <summary>
/// 撤销重复操作管理器
/// </summary>
class UndoStackManager
{
/// <summary>
/// 撤销栈
/// </summary>
Stack<IUndoableOperate> un_stack = new Stack<IUndoableOperate>();
/// <summary>
/// 重复栈
/// </summary>
Stack<IUndoableOperate> re_stack = new Stack<IUndoableOperate>();
public void ClearStack()
{
this.un_stack.Clear();
this.re_stack.Clear();
}
/// <summary>
/// 获取一个值,指示是否有可撤销的操作
/// </summary>
public bool CanUndo
{
get
{
return un_stack.Count != 0;
}
}
/// <summary>
/// 获取一个值,指示是否有可重复的操作
/// </summary>
public bool CanRedo
{
get
{
return re_stack.Count != 0;
}
}
/// <summary>
/// 撤销上一操作
/// </summary>
public void Undo()
{
if (this.CanUndo)
{
IUndoableOperate op = un_stack.Pop();
op.Undo();
re_stack.Push(op);
}
}
/// <summary>
/// 重复被撤销的操作
/// </summary>
public void Redo()
{
if (this.CanRedo)
{
IUndoableOperate op = re_stack.Pop();
op.Redo();
un_stack.Push(op);
}
}
/// <summary>
/// 将某一操作存放到撤销栈中
/// </summary>
/// <param name="op"></param>
public void PushToUndoStack(IUndoableOperate op)
{
this.un_stack.Push(op);
this.re_stack.Clear();
}
}
以下是完整的示例代码:
完整的示例代码
示例代码的执行结果是:
do operate1
do operate2
undo operate2
undo operate1
do operate1
do operate2
- 文本编辑器中,如何设计 撤销/重复栈
- 文本编辑器中,如何设计 撤销/重复栈
- 文本编辑器中,如何设计 撤销/重复栈
- C# 自定义文本编辑器控件中 中文重复出现问题
- vi编辑器中如何复制粘贴文本
- 文本编辑器设计
- 【转】vi编辑器中如何复制粘贴文本
- 基于EditText实现一个可以对编辑文本进行撤销与返回的文本编辑器
- Delphi文本编辑器的设计
- 文本编辑器的粗略设计
- EXCEL中如何撤销工作表保护
- 如何在Git中撤销一切
- 如何在Git中撤销一切
- 如何在Git中撤销一切
- 如何在Git中撤销一切 | 干货
- 如何在Git中撤销一切
- 如何在Git中撤销任何操作
- 在Oracle中如何删除表中设计重复数据
- 拿到资产目录下的xml文件,并解析xml文件
- HTML 5 <input> type 属性
- 五大常用算法之五:分支限界法
- Android 事件总线Otto使用入门一
- Category 类扩展,就是给原有类的添加方法。
- 文本编辑器中,如何设计 撤销/重复栈
- 一个Spark SQL查询的一生
- eclipse安装maven插件
- ui-router中路由的二级嵌套
- 淡疼的itoa和abs: 'itoa' was not declared in this scope; 'abs' was not declared in this scope
- 推荐系统实践读书笔记一
- 【技巧】windows常用技巧
- html中radio值的获取、赋值、注册事件示例详解
- NetRouter 7620 7688 7628 百度语音识别测试