Document directory
- Gof Definition
- Motivation
- Key Points of command mode
Gof Definition
Encapsulate a request as an object so that you can parameterize the customer with different requests, queue requests or record request logs, and support auditable operations.
Motivation
During the software build process, "behavior requestor" and "behavior implementer" usually present a "tightly coupled ". But in some cases-for example
It is inappropriate to perform "record, cancel/Redo (Undo/Redo), transaction" and other operations on the behavior. In this case, how can we decouple "behavior requestor" from "behavior implementer? Abstract A group of behaviors as objects to achieve loose coupling between them.
Let's take a look at a counterexample (version 1). Assume that a large number of external classes are required in an application, and you need to perform operations such as Undo and record on the operations in these classes, if the implementation is as follows, it will be messy and not easy to implement:
Public class application {public void process () {document DOC = new document (); Doc. showtext (); graphics gra = new graphics (); gra. draw (); // undo record operations required} public class document {public void showtext () {}} public class graphics {public void draw (){}}
To meet the requirements mentioned above, you need to use the command mode. The command mode structure is as follows:
The improved code (version 2) abstracts the showtext draw behavior and puts it in an interface. The interface is named icommand and there is a method signature undo in this interface, it is used for revocation. You can add other operations as needed. The icommand code is as follows:
public interface ICommand{ void Execute(); void Undo();}
The document class and graphics class implement this interface and provide their own implementation. The Code is as follows:
Public class document: icommand {public string name {Get; set;} public document (string name) {name = Name;} public void execute () {console. writeline ("show text" + name);} public void undo () {console. writeline ("unshow text" + name) ;}} public class graphics: icommand {public string name {Get; Set ;} public graphics (string name) {name = Name ;} public void execute () {console. writeline ("Drawing" + name);} public void undo () {console. writeline ("cancel drawing" + name );}}
Code called by the client:
public class Application{ public Stack<ICommand> stack=new Stack<ICommand>(); public void Show() { foreach (ICommand cmd in stack) { cmd.Execute(); } } public void Undo() { ICommand command = stack.Pop(); command.Undo(); }}
static void Main(string[] args){ Application app = new Application(); app.stack.Push(new Document("1")); app.stack.Push(new Graphics("1")); app.stack.Push(new Document("2")); app.stack.Push(new Graphics("2")); app.Show(); app.Undo(); Console.ReadLine();}
The above code runs as follows:
It can be seen from the results that the final execution of drawing 2 was revoked.
In the above Code, classes such as document and graphics all implement the icommand interface. If such classes already exist in the project, you must implement these classes to implement the icommand interface, obviously not very reasonable, you need to add the documentcommand class for conversion. The complete code is as follows (version 3 ):
Public class document {public void showtext () {console. writeline ("show text") ;}} public class graphics {public void draw () {console. writeline ("Drawing") ;}} public interface icommand {void execute (); void undo ();} /// <summary> // specific document command class // </Summary> public class documentcommand: icommand {document _ Doc; Public documentcommand (document DOC) {_ Doc = Doc;} public void execute () {_ Doc. showtext ();} public void undo () {console. writeline ("unhide text") ;}/// <summary> /// the specific image command class /// </Summary> public class graphicscommand: icommand {graphics _ GRA; Public graphicscommand (Graphics GRA) {_ gra = GRA;} public void execute () {_ gra. draw ();} public void undo () {console. writeline ("cancel drawing") ;}} public class application {public stack <icommand> stack = new stack <icommand> (); Public void show () {foreach (icommand CMD in stack) {cmd. execute () ;}} public void undo () {icommand command = stack. pop (); command. undo () ;}} class program {static void main (string [] ARGs) {application APP = new application (); app. stack. push (New documentcommand (new document (); app. stack. push (New graphicscommand (new graphics (); app. show (); app. undo (); console. readline ();}}
In version 1, the application class is directly coupled with the methods in document. After step-by-step improvement, the application class is only coupled with the abstract coupling of document and graphics, achieving the goal of decoupling.
Key Points of command mode
- The fundamental purpose of the command mode is to decouple the "behavior requestor" from the "behavior implementer". In object-oriented languages, the common implementation method is "abstract behavior as an object ".
- The specific command object concretecommand that implements the command interface may sometimes save some additional status information as needed.
- By using the composite mode, you can encapsulate multiple "commands" into a "composite command" macrocommand.
- The command mode is similar to the delegate mode in C. However, there is a difference between the two defined behavior interface specifications: Command defines behavior interface specifications with "interface-Implementation" in the object-oriented model, which is stricter and more in line with abstract principles; delegate defines behavior interface specifications using function signatures, which is more flexible, but has weak abstraction capabilities.
Return to the beginning (INDEX)