设计模式之命令模式

命令模式

别名

Action、Transaction、Command

概念

Command is a behavioral design pattern that turns a request into a stand-alone object that contains all information about the request. This transformation lets you pass requests as a method arguments, delay or queue a request’s execution, and support undoable operations.

命令模式是一种行为设计模式 它可将请求转换为一个包含与请求相关的所有信息的独立对象 该转换让你能根据不同的请求将方法参数化 延迟请求执行或将其放入队列中 且能实现可撤销操作

场景

有这样一个UI界面,用户可以编辑文本。用户可以通过

  • 点击工具栏的复制按钮
  • 右键菜单的复制选项
  • 按下ctrl+c

这几种方式复制一段文本,这时候你可以在这三种场景下,调用某一个copy方法,并将需要复制的文本内容,光标位置,是否能全部拷贝,这些信息作为参数传达给这个方法。

这样的实现将UI与业务逻辑层绑在了一块,非常不灵活。推荐的做法的是将复制封装成一个command对象,在这3个场景下面仅仅调用这个命令即可。

原先对方法的调用改成对command实例的调用,原先传递给方法的参数,将作为command的各种成员变量,在构造的时候被传递。

优势

  • 充当中间层,进一步将UI界面与业务逻辑分离,原先UI层访问业务逻辑层的具体方法,现在UI层仅仅负责触发命令,不了解命令的内部实现,也不了解命令的执行时机。命令可能被装载到一个执行队列中,在某个时机被执行
  • 方便实现 Undo/Redo 操作

案例

首先定义一个接口,用来指定命令的执行方法

    public interface ICommand
    {
        void Execute();
    }

 

接着根据业务需求,实现一批Command

    class FirstCommand : ICommand
    {
        private string _text;

        public FirstCommand(string text)
        {
            this._text = text;
        }

        public void Execute()
        {
            Console.WriteLine($"First Command Execute");
        }
    }

 

编写Manager类,负责管理Command

        class CommandManager
        {
            private List<ICommand> _commands = new List<ICommand>();
            public void Execute(ICommand command)
            {
                this._commands.Add(command);
                command.Execute();
            }

            public void Undo()
            {
                var command = this._commands.Last();
                if(command != null)
                {
                    // ...
                }
            }

            public void Redo()
            {
                var command = this._commands.Last();
                if (command != null)
                {
                    // ...
                }
            }
        }

实际应用中不需要向上面立即执行Command,可以将执行Command的逻辑委托给另外一个类,这个类负责在特定时机执行Command

new CommandManager().Execute(new FirstCommand("xxx"));
posted @ 2022-10-06 10:58  内心澎湃的水晶侠  阅读(34)  评论(0编辑  收藏  举报