COMP5028 Object Oriented Analysis and Design Semester 2, 2004 1 Laboratory session Six Storie Dixson 432 A,B Wednesday Sep 8, 2004 School of Information Technologies The University of Sydney SOLUTION Objective • Understand COMMAND pattern • Understand the message exchange in the COMMAND pattern • Being able to implement simple COMMAND pattern design Tasks A. Figure 6.1 illustrate a design class diagram for a simple calculator. This calculator can only perform integer addition and subtraction operations. It keeps a history of all operations it has performed so far and can redo or undo previous operations for unlimited times. Identify different participants in this Command pattern such as “Invoker”, “Receiver”, “Client” and “Concrete Command”. Figure 6.1 Simple Calculator system (The Invoker, Receiver, Client and Concrete Command are all illustrated in the code sample) B. Draw a sequence diagram to show the message exchange when client invokes an AddCommand in the calculator COMP5028 Object Oriented Analysis and Design Semester 2, 2004 2 (There are many alternative ways to draw this diagram, students might create the Calculator in TestCalculator rather than in User, which is indeed a better solution) C. Write a simple implementation of this calculator in Java. The code for TestCalculator is given below. This application is adapted from the C# sample given here http://www.dofactory.com/patterns/PatternCommand.aspx You will get some helpful hints or even pieces of code from there. You can download and try the demonstration from the course web. Run it: java –jar tc.jar. COMP5028 Object Oriented Analysis and Design Semester 2, 2004 3 TestCalculator.java: import java.util.ArrayList; interface Command{ public void execute(); public void unexecute(); } //concrete method 1 class AddCommand implements Command{ int operand; Calculator calculator; //Constructor public AddCommand (Calculator calculator, int operand){ this.calculator = calculator; this.operand = operand; } public void execute(){ calculator.add(operand); } public void unexecute(){ calculator.sub(operand); } } //concrete method 2 class SubCommand implements Command{ int operand; Calculator calculator; //Constructor public SubCommand(Calculator calculator, int operand){ this.calculator = calculator; this.operand = operand; } public void execute(){ calculator.sub(operand); } public void unexecute(){ calculator.add(operand); } } COMP5028 Object Oriented Analysis and Design Semester 2, 2004 4 // "Receiver" class Calculator{ private int total = 0; public void add(int operand){ total += operand; System.out.println("Total becomes " + total +" after + " + operand); } public void sub(int operand){ total -= operand; System.out.println("Total becomes " + total + " after - " + operand); } } //"Invoker" class User{ private Calculator calculator = new Calculator(); private ArrayList commands = new ArrayList(); private int current = 0; public void redo (int levels){ System.out.println("---- Redo " + levels + " levels "); for (int i = 0; i < levels; i ++) if (current < commands.size() -1) ((Command)commands.get(current++)).execute(); } public void undo (int levels){ System.out.println("---- Undo " + levels + " levels "); for (int i = 0; i < levels; i ++) if (current > 0) ((Command)commands.get(-- current)).unexecute(); } public void compute (char operator, int operand){ // create command option and execute it Command command; switch (operator){ case '+': command = new AddCommand(calculator,operand); break; case '-': command = new SubCommand(calculator, operand); break; default: command = new AddCommand(calculator, operand); break; COMP5028 Object Oriented Analysis and Design Semester 2, 2004 5 } command.execute(); //Add command to history commands.add(command); current ++; } } // client public class TestCalculator{ public static void main(String argv[]){ // create user and let her compute User user = new User(); user.compute('+', 100); user.compute('-', 50); user.compute('-', 2); user.compute('+', 20); // undo the previous 3 operations user.undo(3); // redo the previous 2 operations user.redo(2); } }