Using the Command mode to implement the revocation mechanism [1]
Writen by matt berther
Translated by Allen Lee [2]
Reviewed by Teddy Tam & Allen Lee
Introduction
Command is a very powerful design pattern, which is to package a request into an object, allowing you to pack different requests from the client (Queue) or log recovery to a parameter. And also supports the revocable operation.
One of this mode is that it can reduce the degree of coupling between the objects and the actual knowledge of the object that performs an operation.
Today, I want to introduce you how to use this Command mode to achieve the revocation function. As for our example, we will develop a very simple category (Notepad Clone). You don't have to be stunned, because this (a notebook) has been able to show this mode.
The code
The first thing we have to do is to create an abstraction (Abstract) for packaging the TextBox control. In the Command mode, this abstraction layer is called a reciever. In our example, this recipient is an object called Document.
Class
Document
{Private TextBox TextBox; Public Document (TextBox TextBox) {this.textBox = TextBox;} public void boldselection () {text = string.format (" {0} b>",} public void Underlineselection () {text = string.format (" {0} u>", text);} public void italicizeselection () {text = string.format (" {0} i> ", Text); public void cut ();} public void copy ();} public void paste ();} public void paste ();} public string text {Get {Return TEXTBOX.TEXT;} set {textbox.text = value;}}}
We want to define the operation for the Document object that can be performed with the current document and fully decouple this feature from our main program. When the currently selected text is changed to the black body, if you want to change this setting, we should return to this object instead of the interface code.
Then we need to design the interface of Command [3]. Since some commands do not require undo function (such as "copy"), we need to create two base classes (Command and undoableCommand). We will see how to integrate UndoableCommand later. Now, you only need to remember that this is a class for inheriting by other commands that need to be revoked. public
Abstract
Class
Command
{Public abstract void execute ();
public
Abstract
Class
UndoableCommand: Command
{Public abstract void undo ();
As we complete our app and join menu items, we will see that we need a Command object to handle each of these menus. So, to deal with black bodyization, let's write down the following code:
Class
Boldcommand: undoableCommand
{Private Document document; private string previousText; public BoldCommand (Document doc) {this.document = doc; previousText = this.document.Text;} public override void Execute () {document.BoldSelection ();} public override void Undo ( ) {Document.text = previoustext;}}
By creating a document object to package TextBox, we can reduce the coupling between the objects (menu items) that will perform an operation (menu item) and actually know how to handle the object (document object) of the action (document object).
The remaining command object is very similar to the above, so I will not introduce all the code, and these code can be downloaded.
Next we need a CommandManager that integrates all these commands together. CommandManager is a very simple class that has only one stack inside, which is used to save and track our commands with revocation.
Class
CommandManager
{Private Stack commandStack = new Stack (); public void ExecuteCommand (Command cmd) {cmd.Execute (); if (cmd is UndoableCommand) {commandStack.Push (cmd);}} public void Undo () {if (commandStack. Count> 0) {UndoableCommand CMD = (UndoableCommand) CommandStack.Pop (); cmd.undo ();}}}
From the above code we can see that we only add those commands that are undoableCommand to the revocation stack. Remember that I have said that we will see how to integrate it (UndoableCommand)? This is what. We don't want to add commands that do not have revocation functions to join the team. If a user attempts to undo itself, something that does not support the cancellation function will not respond. The remaining work is to replace the event handler of the menu item (there is a need to replace the tool stop). public
Class
Mainform: System.windows.Forms.form
{Private System.Windows.Forms.TextBox documentTextbox; private CommandManager commandManager = new CommandManager (); private Document document; public MainForm () {// // Required for Windows Form Designer support // InitializeComponent (); document = new Document ( this.documentTextbox);} // a bunch of snipped code private void cutMenuItem_Click (object sender, System.EventArgs e) {commandManager.ExecuteCommand (new CutCommand (document));} private void pasteMenuItem_Click (object sender, System.EventArgs e) {CommandManager.executeCommand (Document);} // etc}
I wrote a complete demonstration program and provided download. Please note that here, this text editor is an unpleasant primary product. And your task, if you are willing to accept, add the reproduction (Redo) functionality for this program [4].
I hope that I have clarified the power of this mode and how to use it to add synthetic functions. It is very easy to add a new command now because you no longer need to touch any existing code.
Comments by Allen Lee
Copyright: The copyright of the article belongs to the original author, this translation is for learning and research. For information on the author and a complete source code, please jump to the USING THE COMMAND PATTERN for undo functionality. Translation work: This article first completed the translation preliminary, and annotated the translation point that needs to be discussed; then submitted to TEDDY for the first review; followed by the related needs and correction of the translation and revised translation points, Teddy browsing the full text complete the second review; finally, after the post-work (including typography), read the full draft. During this time, I am very grateful to Teddy's support for this review. He not only conducts basic reviews in this article, but also uses his sophisticated English translation skills to moisturize this article. Here the original sentence: secondly, we will need to design our command interface. The interface here is a keyword INTERFACE that is different from C #.