Command pattern
A Command pattern is an object behavioral pattern that allows us to achieve complete decoupling between the sender and the receiver. It allows you to encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests.
First define the Command interface.
public interface Command {
public void execute();
public void unExecute();
}
A Calculator is a good example.
public class Calculator {
private int current = 0;
public void operation(char operator, int operand) {
switch (operator) {
case '+':
current += operand;
break;
case '-':
current -= operand;
break;
case '*':
current *= operand;
break;
case '/':
current /= operand;
break;
}
System.out.println("Current value = "
+ current + " after " + operator + " " + operand);
}
}
CalculatorCommand wraps the Calculator.
public class CalculatorCommand implements Command {
private char operator;
private int operand;
private Calculator calculator;
public CalculatorCommand(Calculator calculator,
char operator, int operand) {
this.calculator = calculator;
this.operator = operator;
this.operand = operand;
}
public char getOperator() {
return operator;
}
public void setOperator(char operator) {
this.operator = operator;
}
public int getOperand() {
return operand;
}
public void setOperand(int operand) {
this.operand = operand;
}
public void execute() {
calculator.operation(operator, operand);
}
public void unExecute() {
calculator.operation(undo(operator), operand);
}
// Private helper function
private char undo(char operator) {
char undo;
switch (operator) {
case '+':
undo = '-';
break;
case '-':
undo = '+';
break;
case '*':
undo = '/';
break;
case '/':
undo = '*';
break;
default:
undo = ' ';
break;
}
return undo;
}
}
User invokes calculator.
import java.util.ArrayList;
public class User {
private Calculator calculator = new Calculator();
private ArrayList<Command> commands =
new ArrayList<Command>();
private int current = 0;
public void redo(int levels) {
System.out.println("\n---- Redo " + levels + " levels ");
// Perform redo operations
for (int i = 0; i < levels; i++) {
if (current < commands.size()) {
Command command = commands.get(current++);
command.execute();
}
}
}
public void undo(int levels) {
System.out.println("\n---- Undo " + levels + " levels ");
// Perform undo operations
for (int i = 0; i < levels; i++) {
if (current >= 0) {
Command command = commands.get(--current);
command.unExecute();
}
}
}
public void compute(char operator, int operand) {
// Create command operation and execute it
Command command = new CalculatorCommand(
calculator, operator, operand);
command.execute();
// Add command to undo list
commands.add(command);
current++;
}
}
To test it
public class TestCommandPattern {
public static void main(String[] args) {
// Create user and let her compute
User user = new User();
user.compute('+', 100);
user.compute('-', 50);
user.compute('*', 10);
user.compute('/', 2);
// Undo 4 commands
user.undo(4);
// Redo 3 commands
user.redo(3);
}
}
The output
Current value = 100 after + 100
Current value = 50 after - 50
Current value = 500 after * 10
Current value = 250 after / 2
---- Undo 4 levels
Current value = 500 after * 2
Current value = 50 after / 10
Current value = 100 after + 50
Current value = 0 after - 100
---- Redo 3 levels
Current value = 100 after + 100
Current value = 50 after - 50
Current value = 500 after * 10
First define the Command interface.
public interface Command {
public void execute();
public void unExecute();
}
A Calculator is a good example.
public class Calculator {
private int current = 0;
public void operation(char operator, int operand) {
switch (operator) {
case '+':
current += operand;
break;
case '-':
current -= operand;
break;
case '*':
current *= operand;
break;
case '/':
current /= operand;
break;
}
System.out.println("Current value = "
+ current + " after " + operator + " " + operand);
}
}
CalculatorCommand wraps the Calculator.
public class CalculatorCommand implements Command {
private char operator;
private int operand;
private Calculator calculator;
public CalculatorCommand(Calculator calculator,
char operator, int operand) {
this.calculator = calculator;
this.operator = operator;
this.operand = operand;
}
public char getOperator() {
return operator;
}
public void setOperator(char operator) {
this.operator = operator;
}
public int getOperand() {
return operand;
}
public void setOperand(int operand) {
this.operand = operand;
}
public void execute() {
calculator.operation(operator, operand);
}
public void unExecute() {
calculator.operation(undo(operator), operand);
}
// Private helper function
private char undo(char operator) {
char undo;
switch (operator) {
case '+':
undo = '-';
break;
case '-':
undo = '+';
break;
case '*':
undo = '/';
break;
case '/':
undo = '*';
break;
default:
undo = ' ';
break;
}
return undo;
}
}
User invokes calculator.
import java.util.ArrayList;
public class User {
private Calculator calculator = new Calculator();
private ArrayList<Command> commands =
new ArrayList<Command>();
private int current = 0;
public void redo(int levels) {
System.out.println("\n---- Redo " + levels + " levels ");
// Perform redo operations
for (int i = 0; i < levels; i++) {
if (current < commands.size()) {
Command command = commands.get(current++);
command.execute();
}
}
}
public void undo(int levels) {
System.out.println("\n---- Undo " + levels + " levels ");
// Perform undo operations
for (int i = 0; i < levels; i++) {
if (current >= 0) {
Command command = commands.get(--current);
command.unExecute();
}
}
}
public void compute(char operator, int operand) {
// Create command operation and execute it
Command command = new CalculatorCommand(
calculator, operator, operand);
command.execute();
// Add command to undo list
commands.add(command);
current++;
}
}
To test it
public class TestCommandPattern {
public static void main(String[] args) {
// Create user and let her compute
User user = new User();
user.compute('+', 100);
user.compute('-', 50);
user.compute('*', 10);
user.compute('/', 2);
// Undo 4 commands
user.undo(4);
// Redo 3 commands
user.redo(3);
}
}
The output
Current value = 100 after + 100
Current value = 50 after - 50
Current value = 500 after * 10
Current value = 250 after / 2
---- Undo 4 levels
Current value = 500 after * 2
Current value = 50 after / 10
Current value = 100 after + 50
Current value = 0 after - 100
---- Redo 3 levels
Current value = 100 after + 100
Current value = 50 after - 50
Current value = 500 after * 10