Definition¶
The Command Pattern(命令模式) encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.
Class Diagram¶
The class diagram:
- The
Client is responsible for creating aConcreateCommand and setting itsReceiver . - The
Receiver knows how to perform the work needed to carry out the request. Any class can act as aReceiver . Command declares an interface for all commands. A command is invoked through itsexecute() method, which asks a receiver to perform an action.- The
Invoker holds a command and at some point asks the command to carry out a request by calling itsexecute method.
Example - Remote control¶
The remote control is our
- The
RemoteLoader creates a number ofCommand Objects that are loaded into the slots of the Remote Control. Each command object encapsulates a request of a home automation device. - The
RemoteControl manages a set ofCommand objects, one per button. When a button is pressed, the correspondingButtonWasPushed method on the command. - All
RemoteControl commands implement theCommand interface, which consists of one method:execute .Commands encapsulates a set of actions on a specific vendor class. The remote invokes these actions by calling theexecute() method.
public interface Command { public void execute(); public void undo(); } public class LightOffCommand implements Command{ private Light light; public LightOffCommand (Light light) { this.light = light; } public void execute () { light.off(); } public void undo() {light.on();} } public class LightOnCommand implements Command { private Light light; public LightOnCommand (Light light) { this.light = light; } public void execute () { light.on(); } public void undo() {light.off();} } public class NoCommand implements Command { public NoCommand() { } @Override public void execute() { } @Override public void undo() { } }
public class RemoteControl { private final int NUMSLOT = 7; private Command[] onCommands; private Command[] offCommands; private Command undoCommand; public RemoteControl() { onCommands = new Command[NUMSLOT]; offCommands = new Command[NUMSLOT]; for (int i=0; i< NUMSLOT; i++) { onCommands[i] = new NoCommand(); offCommands[i] = new NoCommand(); } undoCommand = new NoCommand(); } public void setCommand (int slot, Command onCommand, Command offCommand) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } public void onButtonWasPushed(int slot) { onCommands[slot].execute(); undoCommand = onCommands[slot]; } public void offButtonWasPushed(int slot) { offCommands[slot].execute(); undoCommand = offCommands[slot]; } public void undoButtonWasPushed() { undoCommand.undo(); } public String toString() { StringBuilder descritption = new StringBuilder(); descritption.append("n------ Remote Control -------n"); for (int i = 0; i < NUMSLOT; i++) { descritption.append("[slot " + i + "] " + onCommands[i].getClass().getSimpleName() + " " + offCommands[i].getClass().getSimpleName() + "n"); } return descritption.toString(); } }
public class RemoteLoader { public static void main(String[] args) { Light light = new Light(); Stereo stereo = new Stereo(); RemoteControl remoteControl = new RemoteControl(); remoteControl.setCommand(0, new LightOnCommand(light), new LightOffCommand(light)); remoteControl.setCommand(1, new StereoOnWithCDCommand(stereo), new StereoOffWithCDCommand(stereo)); System.out.println(remoteControl); remoteControl.onButtonWasPushed(0); remoteControl.offButtonWasPushed(0); remoteControl.undoButtonWasPushed(); } }
Example - Runnable¶
public interface Runnable { public abstract void run(); } public interface Executor { void execute(Runnable command); } class SerialExecutor implements Executor { private final Queue<Runnable> tasks = new ArrayDeque<>(); private final Executor executor; private Runnable active; SerialExecutor(Executor executor) { this.executor = executor; } public synchronized void execute(Runnable r) { tasks.add(() -> { try { r.run(); } finally { scheduleNext(); } }); if (active == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((active = tasks.poll()) != null) { executor.execute(active); } } }
近期评论