• 轻松实现记录与撤销——C#中的Command模式


    Command模式属于行为模式,作为大名鼎鼎的23个设计模式之一,Command模式理解起来不如工厂模式,单例模式等那么简单直白。究其原因,行为模式着重于使用,如果没有编程实践,确实不如创造模式那么直白。我们先看看UML类图。

    估计很多同学看着图就晕了,那么多东西,Command和Concrete Command还好理解,那些Receiver和Invoker又是什么东西呢?
     
    别着急,只要理解了一点,这个模式就很容易理解了,下面划重点,Command模式最主要的特点,是将命令封装成类,在类中保存命令执行的上下文(即该命令执行的参数,执行的对象),以实现命令执行对象和命令发出对象的解耦
     
    这样一来是不是觉得好理解多了?Command类里面的Receiver,就是命令具体执行的对象。这里的Client可以理解为装配环境,在这里面代码实例化Command。Invoker内部保存命令(可以保存多条命令,实现命令记录查看,撤销等),客户端代码通过Invoker来操作命令。接下来我们看看示例代码。

     

    定义Command接口

    首先我们定义一个支持撤销的Command接口。

        interface Command
        {
            void Execute();
            void Undo();
        }
    

    定义Receiver

    接下来我们定义Receiver,也就是命令的执行对象,这里我们定义一个Ball类。

        class Ball
        {
            public int Size { get; set; } = 10;
            public string Name { get; set; } = "My First Ball";
            public void Inspect()
            {
                Console.WriteLine("My Name is {0} and size is {1}", Name, Size);
            }
        }
    

    定义具体命令

    这里定义两个命令,一个修改名字,一个修改大小。

        class ChangeNameCommand : Command
        {
            private Ball _Ball;
            private string _OldName;
            public string NameYouWant { get; set; }
            public ChangeNameCommand(Ball ball)
            {
                _Ball = ball;
            }
    
            public void Execute()
            {
                _OldName = _Ball.Name;
                _Ball.Name = NameYouWant;
            }
    
            public void Undo()
            {
                _Ball.Name = _OldName;
            }
        }
        
    	class ChangeSizeCommand : Command
    	{
    	//代码大同小异,略
    	}
    

    定义Invoker

    接下来是Invoker,,也就是存储命令,并最终会被用户代码调用的类,这里我们叫它CommandManager。

        class CommandManager
        {
            private Stack<Command> commands = new Stack<Command>();
    
            public void RunCommand(Command command)
            {
                command.Execute();
                commands.Push(command);
            }
    
            public void Undo()
            {
                if (commands.Count > 0)
                {
                    var command = commands.Pop();
                    command.Undo();
                }
            }
            
    		public void ShowCommands()
            {
                var temp = commands.Reverse();
                foreach(var command in temp)
                {
                    //display command
                }
            }
        }
    

    使用命令

    现在我们看看客户端代码是怎么使用他们的,定义Ball,定义命令,通过CommandManager去调用,这样可以方便查看命令记录,撤销命令,等。

            static void Main(string[] args)
            {
                Ball ball = new Ball();
                ball.Inspect();
    
                ChangeNameCommand changeName = new ChangeNameCommand(ball) { NameYouWant = "Changed" };
                ChangeSizeCommand changeSize = new ChangeSizeCommand(ball) { SizeYouWant = 20 };
    
                CommandManager manager = new CommandManager();
                manager.RunCommand(changeName);
                manager.RunCommand(changeSize);
                ball.Inspect();
    
    			manager.ShowCommands();
                
                manager.Undo();
                ball.Inspect();
    
                manager.Undo();
                ball.Inspect();            
            }
    

    就酱,我们已经实现了命令模式,并且还支持命令的记录与撤销,希望能对大家有点帮助。

  • 相关阅读:
    Mybatis——逆向工程
    Mybatis——Spring整合
    Mybatis——缓存机制
    Mbatis——动态SQL
    Mybatis_映射文件配置
    Mybatis XML 配置文件
    渣渣小本求职复习之路每天一博客系列——数据结构与常用算法(2)
    渣渣小本求职复习之路每天一博客系列——数据结构与常用算法(1)
    渣渣小本求职复习之路每天一博客系列——数据库基础(MySQL)(5)
    渣渣小本求职复习之路每天一博客系列——数据库基础(MySQL)(4)
  • 原文地址:https://www.cnblogs.com/deatharthas/p/13021590.html
Copyright © 2020-2023  润新知