Command Examples:

Java
Java
C#
C#
PHP
PHP
Python
Python
C++
C++
TypeScript
TypeScript
▸ Command Quick Review

Writing Text Editor in C#

To showcase the Command pattern, we'll be creating a basic implementation of a text editor. This includes the ability to add content(type it on the page), backspace to remove content, and the ability to undo and redo our actions.

We'll start out with a Document class that will contain the text data and actions to add and remove content:

The Document Class:

using System.Collections.Generic;
using System;

public class Document
{
   string content;

   public Document()
   {
       content = "";
   }

   public void PrintDocument()
   {
       Console.WriteLine(content);
   }

   public void AddContent(string content)
   {
       this.content += content;
   }

   public int Length()
   {
       return content.Length;
   }

   public string CharAt(int index)
   {
       return content[index].ToString();
   }

   public void RemoveContent(int numChars)
   {
       if(numChars < 0) return;
       if(numChars > content.Length - 1)
       {
           content = "";
           return;
       }

       content = content.Remove(content.Length - numChars);
   }
}

Next, we'll want to create an interface for our commands. We'll want to have the usual execute method, in addition to undo and redo methods:

IUndoableCommand

public interface IUndoableCommand
{
   void Execute();
   void Undo();
   void Redo();
}

AddContentCommand

public class AddContentCommand: IUndoableCommand
{
   Document document;
   string content;

   public AddContentCommand(Document document, string content)
   {
       this.document = document;
       this.content = content;
   }

   public void Execute()
   {
       this.document.AddContent(content);
   }

   public void Undo()
   {
       this.document.RemoveContent(content.Length);
   }

   public void Redo()
   {
       this.Execute();
   }
}

BackspaceCommand

public class BackspaceCommand: IUndoableCommand
{
   Document document;
   String removedChar;

   public BackspaceCommand(Document document)
   {
       this.document = document;
       removedChar = null;
   }

   public void Execute()
   {
       removedChar = document.CharAt(document.Length() - 1);
       this.document.RemoveContent(1);
   }

   public void Undo()
   {
       this.document.AddContent(this.removedChar);
   }

   public void Redo()
   {
       this.Execute();
   }
   
}

Lastly, we'll want to create a Document writer that will hold onto a list of our actions in order to undo and redo inputs:

DocumentWriter

public class DocumentWriter
{
   Stack<IUndoableCommand> undoStack;
   Stack<IUndoableCommand> redoStack;

   Document document;

   public DocumentWriter(Document document)
   {
       this.document = document;
       this.undoStack = new Stack<IUndoableCommand>();
       this.redoStack = new Stack<IUndoableCommand>();
   }

   public void Write(string content)
   {
       IUndoableCommand command = new AddContentCommand(this.document, content);

       this.undoStack.Push(command);
       this.redoStack.Clear();

       command.Execute();
   }

   public void Backspace()
   {
       if(this.document.Length() == 0) return;

       IUndoableCommand command  = new BackspaceCommand(this.document);
       this.undoStack.Push(command);
       this.redoStack.Clear();

       command.Execute();
   }

   public void Undo()
   {
       if(this.undoStack.Count > 0)
       {
           IUndoableCommand command = this.undoStack.Pop();
           this.redoStack.Push(command);
           command.Undo();
       }
   }

   public void Redo()
   {
       if(this.redoStack.Count > 0)
       {
           IUndoableCommand command = this.redoStack.Pop();
           this.undoStack.Push(command);
           command.Redo();
       }
   }
}

Demo

public class Solution
{
   public static void Main(string[] args)
   {
       
       Document doc = new Document();
       DocumentWriter writer = new DocumentWriter(doc);

       // Write to the document:
       writer.Write("Hello world!");

       writer.Backspace();
       doc.PrintDocument(); // Hello world
       writer.Undo();
       doc.PrintDocument(); // Hello world!
       writer.Redo();
       doc.PrintDocument(); // Hello world

       writer.Write(" Goodbye!"); 
       doc.PrintDocument(); // Hello world Goodbye!
       writer.Undo();
       doc.PrintDocument(); // Hello world
       writer.Undo();
       doc.PrintDocument(); // Hello world!

   }
}

Find any bugs in the code? let us know!