輕鬆實現記錄與撤銷——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類。code

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。blog

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();            
        }

就醬,咱們已經實現了命令模式,而且還支持命令的記錄與撤銷,但願能對你們有點幫助。get

相關文章
相關標籤/搜索