Command

Introduction

Sometimes it’s necessary to issue requests to objects without knowing anything about the operation being requested or the receiver of the request.

For example, when you’re designing an user interface toolkit, include objects like buttons and menus that carry out a request in response to user input, but you don’t know and you can’t implement the request explicitly in the button or menu because only applications that use the toolkit know what should be done on which object.

The Command pattern lets toolkit make requests of unspecified application objects by turning the request itself into an object, which can be stored and passed around like other objects.

Definition

Encapsulate a request as an object, there by letting you paramaterize clients with different requests, queue or log requests, and support undoable operations.

UML class diagram

Command pattern

Participants

  • Command
    • declares an interface for executing an operation.
  • ConcreteCommand
    • defines a binding between a Receiver object and an action.
    • implements Execute by invoking the corresponding operation(s) on Receiver.
  • Client
    • creates a ConcreteCommand object and sets its receiver.
  • Invoker
    • asks the command to carry out the request.
  • Receiver
    • knows how to perform the operations associated with carrying out a request. Any class may serve as a Receiver.

Example

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

// ConcreteCommand
public class FlipUpCommand implements Command {
	private Light theLight;
	
	public FlipUpCommand(Light light) {
		theLight = light;
	}

	@Override
	public void execute() {
		theLight.turnOn();
	}
}

public class FlipDownCommand implements Command {
	private Light theLight;
	
	public FlipDownCommand(Light light) {
		theLight = light;
	}

	@Override
	public void execute() {
		theLight.turnOff();
	}
}

// Receiver
public class Light {
	private boolean isOn = false;

	public void turnOn() {
		if (isOn) {
			System.out.println("The light is on.");
		} else {
			System.out.println("Turn on the light.");
			isOn = true;
		}
	}

	public void turnOff() {
		if (isOn) {
			System.out.println("Turn off the light.");
			isOn = false;
		} else {
			System.out.println("The light is off.");
		}
	}
}

// Invoker
public class Switch {
	private List<Command> history = new ArrayList<>();
	
	public void storeAndExecute(Command cmd) {
		history.add(cmd);
		cmd.execute();
	}
}

// Client
public class Test {

	public static void main(String[] args) {
		Light light = new Light();
		Command switchUp = new FlipUpCommand(light);
		Command switchDown = new FlipDownCommand(light);
		
		Switch mySwitch = new Switch();
		mySwitch.storeAndExecute(switchUp);
		mySwitch.storeAndExecute(switchDown);
		mySwitch.storeAndExecute(switchDown);
		mySwitch.storeAndExecute(switchUp);
		mySwitch.storeAndExecute(switchDown);
	}
}

Output:

Turn on the light.
Turn off the light.
The light is off.
Turn on the light.
Turn off the light.

Usage

  • When you want to parameterize objects by an action to perform. Commands are an object-oriented replacement for callbacks.
  • When you want to specify, queue, and execute requests at different times.
  • When you want to support undo.
  • When you want to support logging changes so that they can reapplied in case of a system crash.
  • When you want to structure a system around high-level operations built on primitives operations.

See Also

blog comments powered by Disqus