zoukankan      html  css  js  c++  java
  • 撤销与反撤销 功能实现

        你一定经常看见类似下面的图标:
       
        它们就表示“撤销”与“反撤销”。在程序中,这种功能通常是使用Command模式实现的,本文也不例外。首先抽象定义Command,使用ICommand接口:

        public interface ICommand
        {
            
    void Excute() ;
        }

        Excute表示执行该ICommand引用的目标的所包含的动作(或动作序列)。
        
        可撤销的命令也是一种命令,所以从ICommand继承:
       

        public interface IBackableCommand :ICommand
        {
            
    void Undo() ;
        }

        一个可撤销的命令表明调用其Excute方法后,再调用其Undo方法可以使被操作的对象回复到之前的状态。

        为了实现撤销功能,我们需要一个堆栈来记录所有已执行的可撤销命令,为了实现反撤销的功能,同样,我们也需要一个堆栈来记录所有已撤销的命令。这个职责是由ICommandManager接口提供:
       

        public interface ICommandManager
        {
            
    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        
        }


        本文介绍的撤销与反撤销功能是与应用无关的,所以可以在不同的应用中复用,你只需要根据你自己的应用需求来实现对应的ICommand接口和IBackableCommand接口就可以立即使用撤销与反撤销功能了。




  • 相关阅读:
    近期需要学习的
    sdfsdf
    思路绝对清楚,手段绝对下流【转】
    一宅镇京华——看谁还敢在我面前吹丫有钱 
    白天求生存,晚上求发展
    Ten Places to Go for SharePoint Development Information
    Life Record
    Custom Search Result Style Based On SharePoint Xslt Search Result Style
    软考信息系统项目管理师考试记录
    什么是Microsoft SharePoint 2010
  • 原文地址:https://www.cnblogs.com/zhuweisky/p/389244.html
Copyright © 2011-2022 走看看