The Command Pattern encapsulates a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.  It decouples an object, making a request from the one that knows how to perform it.  An invoker makes a request of a Command object by calling its execute() method, which invokes those actions on the receiver.  Macro Commands are a simple extension of Command that allow multiple commands to be invoked.  Likewise, Macro Commands can easily support undo() operations.  In practice, it is not uncommon for "smart" Command objects to implement the request themselves, rather than delegating to a receiver.

An example of the Command Design Pattern follows:


public interface Command {
	public void execute();
	public void undo();
}

public class Light {
	public on() { //  Turn light on! }
	public off() { // Turn light off! }
}

public class LightOnCommand implements Command {
	Light light;
	public LightOnCommand(Light light) {
		this.light = light;
	}
	public void execute() { light.on(); }
	public void undo() { light.off(); }
}

public class RemoteControl {
	Command slot;
	
	public void setCommand(Command command) {
		slot = command;
	}
	public void buttonPressed() {
		slot.execute();
	}
}
//  tester
public class RemoteControlTest {
	public static void main(String[] args) {
		RemoteControl remote = new RemoteControl();
		Light light = new Light();
		LightOnCommand lightOn = new LightOnCommand(light);
		
		remote.setCommand(lightOn);
		remote.buttonPressed();
	}
}

The Macro Command simply creates an array of Command objects to correspond to the buttons on the remote control.  This example includes the single undo option, but if the undoCommand was made into an array, multiple undo operations could be performed.

An example of a Macro Command Design Pattern follows:

public class RemoteControl {
	Command[] onCommands;
	Command[] offCommands;
	Command undoCommand;
	
	public RemoteControl() {
		onCommands = new Command[7];
		offCommands = new Commands[7];
		//  NoCommand is a "do nothing" Command object.
		Command noCommand = new NoCommand();
		undoCommand = noCommand;
		for (int i = 0; i < 7; i++) {
			onCommands[i] = noCommand;
			offCommands[i] = noCommand;
		}
	}
	
	public void setCommand(int slot, Command onCommand, Command offCommand) {
		onCommands[slot] = onCommand;
		offCommands[slot] = offCommand;
	}
	
	public void onButtonPushed(int slot) {
		onCommands[slot].execute();
		undoCommand = onCommands[slot];
	}
	public void offButtonPushed(int slot) {
		offCommands[slot].execute();
		undoCommand = offCommands[slot];
	}
	public void undoButtonPushed() {
		undoCommand.undo();
	}
}