RSS Feed for This PostCurrent Article

Design Pattern in Java 101 – Command Pattern (Behavioral Pattern)

Download Sample Code

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.

Here is a rewrite of the C# example provided in dofactory.com.

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


Trackback URL


RSS Feed for This Post1 Comment(s)

  1. Yanic | Jan 27, 2008 | Reply

    Hi,

    I’ve used your java design patterns sample code of the previous few posts to test my sequence diagram generator for Trace Modeler.

    It worked nicely :o)

    I already knew the patterns of course, but it was amazing how fast I could understand your particular examples from a single sequence diagram.

    Let me know if you want the resulting images, would be a nice addition to your posts.

    Best regards,
    Yanic

Sorry, comments for this entry are closed at this time.