Chaper 6 Notes – Command Pattern Context 1. A good use of the Command Pattern is in the design of an undo/redo feature in a software system. Suppose we want to design a simple word processing application. We might define an Editor class (shown at right) with methods to modify the data (document). Now, suppose that we want to support an undo feature that reverses the most recent command. If the most recent command was to insert a word with the InsertString method, how would we undo this insertion? We’d need to know the word and where in the text the word appeared. Then, we could use the Delete command to remove the word. 2. So, how would we implement this? Add an Undo method to the Editor class? However, it’s implementation would be messy because of an if statement that would be needed to decide what “type” the most recent command was, and the logic to undo each case, as well as store the relevant data. Suppose we wanted to support a multi-level undo – where and how would we store the operations and associated data? Finally, as new features are developed, adding new commands, we would have to modify the undo method. This is not acceptable. This class is not cohesive. 3. We should encapsulate each possible interaction the user can initiate. For instance, the InsertStringCommand as shown at right. We have a command object just for inserting a block of text, later removing it, and for storing the location and length of the text. 4. If we envision the many such classes we will have, then we see that any component that depended on them would be highly coupled and it’s maintainability would be low. We should remember the design principle: depend on abstractions, not on implementations. So, we introduce a superclass, Command which specifies two behaviors: doit and undoit. Each individual command class knows how to implement doit and undoit for that particular user action. 1 5. To implement a multi-level undo, we set up the following structure: As commands are requested: a. Construct an instance of the appropriate subclass which will be a Command b. Tell the Command to doit(), which executes the command c. Put the Command on a stack of previous commands to maintain a history. If an undo is requested a. Pop the stack, returning a Command object. b. Tell the Command to undoit() General Problem You can use the Command Pattern when you need to: Control the sequencing , selection, or timing of command execution Support undo and redo operations Maintain a persistent log of commands that have been executed. You can enhance the doit and undoit methods to support this requirement. 2 General Solution 1. To think more generally about this situation, consider this class diagram: a. ConcreteCommand – This class encapsulates a specific command (e.g. InsetString). The constructor supplies any parameters that the command requires. Usually, there will be at least one parameter, the object that the command operates on. Sometimes, this class is called the Receiver. b. Receiver – The object that the action is taken on (e.g. a word processing document) c. Client – Creates ConcreteCommands pairing them with the appropriate Receiver and sets them in the Invoker. d. Invoker – This class manages the Command objects. As shown above, it maintains a pending set of commands and a history. At some later point, the Client (or other mechanism) can tell the Invoker to invoke the Commands. As each Command is executed, it is pushed onto the history stack. This class can be made independent of the application in which it is used so that it can be reusable. 2. This implementation is extensible in a number of ways: a. The timing, selection and sequencing of the invocation can be controlled by the implementation of the invoke method. b. The initiator of the invocation can vary. For instance, the client shown in the figure above can call invoke, or, another client can. c. Allows the receiver of the command to vary d. New commands are easy to implement as they are minimally coupled with the Command interface. 3 3. This model also supports the addition of macro commands, e.g. commands that do multiple things. With this model, then a macro command is just a collection of commands. 4. The Command pattern also supports the notion of transactions where a transaction is a series of Commands that must all be executed correctly, or completely fail. In other words, as a transaction is being carried out, if a problem results, then the transaction is rolled-back, undoing the earlier commands. Databases often have this feature. Implementation 1. The most important decision is to determine what the commands will be. If the commands are issued by a user through a GUI, then a natural way to determine commands is to have a command class for every action the user can carry out. Some commands may be complex and sometimes a more simplistic solution is to implement these complex commands as a series of simpler commands. Similarly, if the number of commands is very large, combinations of commands can be used. 2. Another implementation issue is capturing the state information required to undo commands. Some commands may not be able to be undone. For instance, a global search and replace operation may require that too much information be stored. Similarly, commands that involve deletion of files may not be able to be undone. 3. The Invoker must be aware when a command cannot be undone and responsible for informing the user, allowing them to back out before the command is executed. After a command that cannot be undone is executed, the command history does not need to be maintained. 4 An Extension to Avoid GUI Dependencies 1. The Java API doesn’t contain any good examples of the Command Pattern. However, the Button class and MenuItem class contain methods: getActionCommand and setActionCommand(name:String) which facilitate the use of the Command Pattern in the context of GUI’s. Instead of requiring GUI component classes to know the concrete class for the associated command object, you can embedded the name of a command in the GUI component and then use a factory method to create the command objects. 2. Command Pattern used in WPF – Developed by Microsoft, the Windows Presentation Foundation (or WPF) is a computer-software graphical subsystem for rendering user interfaces in Windows-based applications. WPF introduces routed commands, which combine the command pattern with event processing. As a result the command object no longer contains a reference to the target object nor a reference to the application code. Instead, invoking the command object's execute command results in a (so called Executed Routed Event) which during the event's tunneling or bubbling may encounter a (so called binding) object which identifies the target and the application code, which is executed at that point. Consequences 1. The object that requests that a command be executed (a client) is not the same object that executes a command the Invoker). This separation provides flexibility in the timing and sequencing of commands. 2. Completely decouples sender and receiver of a message 3. Being able to collect and control the sequencing of commands means that you can use the Command Pattern as the basis of a mechanism that supports the construction of macros. A macro records a sequence of commands and allows them to be replayed later. 4. Adding new commands is generally easy. 5 General UML 1. The Command Pattern encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations. 2. Below, a sequence diagram shows a possible scenario. Here, we show the Client telling the Invoker to invoke the command. In practice, this could be any other object, including the invoker itself. 6 Other Examples 1. Suppose we want to log all actions taken on some object. 2. Suppose we want to implement a progress bar. 3. Suppose we want to design a wizard that will build a Blob in steps. We can use the Builder, Factory, and Command patterns. The Gui (or Gui model) can act as the Director. The Builder (Wizard) uses a Factory to construct the Steps (Commands) and place them in an Invoker. Finally, when the user chooses “Finish”, the Director tells the Wizard to finish which tells the Invoker to carry out the Steps. 4. Task Scheduling –Generic task scheduling service allow tasks to be scheduled by interval (e.g., every hour), date/time (e.g., on February 8th at 1:00pm), etc. Tasks are defined using Command objects. Scheduling service executes Command object at the appropriate time, having no idea what it actually does 7 Text Discussion 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. On page 195, Mary says, “...we don’t want the remote to have to know the specifics of the vendor classes.” Discuss a design principle that should be used to meet this requirement. Why is it important in this case? (Omit) Re-read Joe’s definition of a “command object” 4 or 5 times. Now, restate it in your own language? Draw a class diagram, as complete as possible from the analogy on page 199. Feel free to draw on your complete understanding of the chapter. Consider the Objectville Diner analogy on page 199. Now consider the command pattern diagram on page 201. Substitute the appropriate class name for each of the names on the diagram (e.g. who is the invoker in the diner? command, invoker, receiver) Consider the Remote Control problem in the text as described through page 205. Now consider the command pattern diagram on page 201. Substitute the appropriate class name for each of the names on the diagram (e.g. what is the client in the remote control problem? command, invoker, receiver) The command pattern definition says, “...letting you parameterize other objects...” In the lingo of the command pattern, what is/are these “other objects”? (Omit) Study the UML on page 207 carefully. Assess each association or lack of association. The UML is correct; however, can you question the validity of any of the associations or lack of associations? (I see several things I would change). Explain why. Describe how a factory pattern could be used with the command pattern. Suppose there was a pool of equivalent Receiver objects and they need to be assigned just as a command was about to be executed (e.g. a load-balancer). How could you modify this classic command pattern situation? Would it still be the command pattern? (Omit) What is the null object design pattern? Why is it useful? Consider undo as it is described on pages 216-219. Describe in your own words how undo is implemented. Draw a class diagram of the Remote example that supports Undo. Show methods. You only need to show a few commands. Why is state information sometimes needed when implementing undo. Describe how the macro command is implemented? (Omit) How do you implement multiple undo’s? Briefly describe in your own words, the use of the command pattern in queuing requests. (Omit) Briefly describe in your own words, the use of the command pattern in logging requests. The text says that we need to add two methods for each Command: store and load. Presumably, when a Command is executed, it is also stored. Not sure how this works, exactly. 8 Combing Command with other Patterns 1. Commands can be decorated: 2. Commands can be Observable 9 3. We can provide hooks when we use the Command pattern so that when a command is executed, a hook is called either before or after (or both) the an action is performed on the receiver. One way to provide a hook is to use subclassing as in the Template Method pattern: 4. Another way is to use composition as with Strategy Pattern. 10 References 1. Rice.edu - Brief explanation of pattern. 2. JavaWorld - Wired home appliances 3. Object Factory - Calculator 4. Design Nation - simulation of a battle 5. Java2s - Menus and Shopping examples 6. Wikipedia - brief descriptions of progress bar, wizard, thread pool, macro recording 7. Code Project - builds a simple text editor with undo functionality 8. Code Project - Distributed Command Pattern, slightly different 9. JavaWorld - Command pattern and Swing 10. Surf - brief scheduling and Swing examples 11. Oracle – Coherence- Command Pattern 12. Blog – Command pattern in Silverlight 11