编辑器的模式(1)—undo/redo

"我不能预见每个人的未来,我只能预见我自己的,而且只能预见两分钟"——尼古拉斯.凯奇《惊魂下一秒》2007

无论人写字,画画一样,我们常常有笔误不可避免,
回到过去的某个修改点,做出不同的修改,并继续,

在程序设计的概念里,这常常指版本管理,版本管理保存了每一次(所有)修改的历史,不同时间线,还有合并

图1:版本管理

而编辑器的,undo/redo, 则有几点简化,

  1. 只保留一部分修改记录——通常我们只关心近期的修改,
  2. undo/redo 为逆操作,但undo不销毁历史,而任何undo之后的修改,则会销毁redo序列
图2:undo/redo历史线

这像是《惊魂下一秒》里的故事,修正有限历史,并让下一秒冲刷掉未来。

undo/redo模式,即为,维护一定长度的修改点队列,并在所有历史修改点里,进行版本切换.

以下我实现了一个简单的undo/redo,版本管理,

//版本数据库,为了实现备份,data须可clone  
public class DataBackup<Data> where Data : class, ICloneable, new()
{
    //版本队列
    List<Data> mDataBackup = new List<Data>() { new Data() };
    const int MAX_LEN = 15;//版本历史限制
    int dataIdx = 0;//版本号

    public Data data
    {
        get
        {
            return mDataBackup[dataIdx];
        }
    }

    private void trim()
    {
        mDataBackup.RemoveRange(dataIdx + 1, mDataBackup.Count - dataIdx - 1);
    }
    
    //备份
    public void backup()
    {
        trim();//消除所有未来版本
        mDataBackup.Add(data.Clone() as Data);
        if (dataIdx > MAX_LEN)
        {
            mDataBackup.RemoveAt(0);
        }
        dataIdx = mDataBackup.Count - 1;
    }

    //撤销
    public void undo()
    {
        dataIdx--;
        if (dataIdx < 0)
            dataIdx = 0;
    }

    //重做
    public void redo()
    {
        dataIdx++;
        if (dataIdx >= mDataBackup.Count)
            dataIdx = mDataBackup.Count - 1;
    }
}
图三. 撤销/重做测试

可以看到,这样简单的undo/redo已经足够工作。

实现更精巧的 redo/undo功能,你需要考虑以下问题:

  • 当data特别大,每一个版本仅需要保存版本增量,因此需要实现,
    gain(data_v1, diff) == data_v2
    revert(data_v2, diff) == data_v1

  • MVC模式下,不一定是对于modeller的数据集, 每次备份能可以是controller 操作集 action list,因此control需要实现 一组可逆接口,例如,
    addEntity/removeEntiy
    changeDeltaPos(x, y) / changeDeltaPos(-x, -y)

而现实中,对于有些编辑器的实现来说,效率并不是一个严重的问题,简单则是更为重要的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 个人自行阅读时候,翻译的文档。因为比较渣,如果有更合理或者错误的地方烦劳告知,我会做修改。Oracle Data ...
    窝窝的小黑屋阅读 4,987评论 0 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,092评论 19 139
  • 什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点。 原子性:要不全部成功,要不全部撤销 隔...
    jiangmo阅读 4,755评论 0 3
  • 背景: 阅读新闻 12C CDB模式下RMAN备份与恢复 [日期:2016-11-29] 来源:Linux社区 作...
    阳屯okyepd阅读 9,034评论 0 7
  • 终于,要再快年底的时候,以回家过节的名义,要离开北京了。初次与北京见面,是在14年12月初的时候,那时候,地铁还是...
    QshawQ阅读 3,890评论 0 0

友情链接更多精彩内容