Command pattern
The command pattern uses the command objects that decide who can handle this command.
Commands are also known as an object-oriented replacement for callbacks.
This pattern is useful in GUI implementations and gaming applications. The input data is transformed into meaningful commands. For example, the Action interface in Swing represents a command.
You can think about this pattern when you have code like
void turnOn(Object receiver){
if(receiver instanceof TVset){
// perform command on receiver
}else if(receiver instanceof Lamp){
// perform command on receiver
}...
}
advantages
- Decouples the command senders from the command performers.
- Allows you to control commands, such as when and who will execute them.
- Adding new command will be easy, without changing the existing code.
command vs strategy
The command object is defined by what needs to be done. For example, it can take an operation and its arguments and wrap them up in an object to be logged, held for undo, etc.
The strategy object defines how something should be done, and plugs into a larger object or method to provide a specific algorithm.
example
/* The Command interface */
interface Command {
void execute();
// optionally you can add other methods like
// void undo();
}
// receiver of command
class Receiver extends ReceiverA {
void cmd1() {/* ... */}
void cmd2(int arg) {/* ... */}
// ...
}
// Concrete command
class Cmd1 implements Command {
private ReceiverA receiver;
Cmd1(ReceiverA receiver) { this.receiver = receiver; }
@Override
void execute() { receiver.cmd1(); /* do extra things */ }
}
// Concrete command
class Cmd2 implements Command {
private ReceiverA receiver;
private arg;
Cmd2(ReceiverA receiver, int arg) {
this.receiver = receiver;
this.arg = arg;
}
@Override
void execute() { receiver.cmd2(arg); /* do extra things */}
}
// Invoker of commands
class CommandManager {
private List<Command> history = new ArrayList<>();
public CommandManager() {
}
public void execute(Command command) {
history.add(command);
command.execute();
// doing other things
}
// ...
}
/* The client */
class DemoClient {
void test(){
commandManager.execute(new Cmd1(someReceiver));
}
}
/* When you need only one receiver object */
// Invoker of commands
class CommandManager2 {
private List<Command> history = new ArrayList<>();
private ReceiverA receiver; // we can have several
public CommandManager(ReceiverA receiver) {
this.receiver = receiver;
}
public void execute(Command command) {
history.add(command);
command.execute();
// doing other things
}
Cmd newCmd1() { return new Cmd1(receiver); }
// ...
}