定义
将一个请求封装成一个对象,从而可以用不同的请求对客户参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
UML
public interface Command {
/**
* 执行命令具体的操作
*/
void execute();
}
/**
* 具体的命令实现对象
*/
class ConcreteCommand implements Command{
/**
* 接收者
*/
private Receiver receiver = null;
/**
* 命令对象可以有自己的状态
*/
private String state;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
class Receiver{
public void action(){
System.out.println("真正的操作");
}
}
class Invoker{
private Command command = null;
public void setCommand(Command command) {
this.command = command;
}
public void runCommand(){
command.execute();
}
}
class Client{
/**
* 负责创建命令对象,设定接收者
*/
public void assemble(){
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.runCommand();
}
}
Command和ConcreteCommand分别是命令的抽象和实现。
Receiver:接收命令的对象。
Invoker:要求命令对象执行请求。使用命令对象的接口。
特点
- 命令模式将动作的请求者和动作的执行者解耦。
- 如果命令类过多,可能会增加复杂度。
- 空命令也是一种命令。
- 命令可以放置到队列里,可以多线程的执行命令。
- 命令模式有利于实现请求的撤销和重做。
示例
例如要给一个遥控器上的按钮设置可编程命令,on表示打开,off表示关闭。
先加一个命令试试:
public interface Command {
void execute();
}
class Light{
public void on(){
System.out.println("电灯打开");
}
}
class LightOnCommand implements Command{
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
class SimpleRemoteControl{
Command slot;
public void setCommand(Command command){
slot = command;
}
public void buttonWasPressed(){
slot.execute();
}
}
class RemoteControlTest{
public static void main(String[] args) {
SimpleRemoteControl remote = new SimpleRemoteControl();
Light light = new Light();
LightOnCommand lightOn = new LightOnCommand(light);
remote.setCommand(lightOn);
remote.buttonWasPressed();
}
}
将7个插槽全部编入命令,注意NoCommand也是一种命令
public interface Command {
void execute();
}
/**
* NoCommand表示空的命令,什么也不做即可。
*/
class NoCommand implements Command{
@Override
public void execute() {
System.out.println("do nothing");
}
}
class Light{
private String name;
public Light(String name) {
this.name = name;
}
public void on(){
System.out.println(name + "电灯打开");
}
public void off(){
System.out.println(name + "电灯关闭");
}
}
class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
class RemoteControl{
Command[] onCommands,offCommands;
RemoteControl(){
onCommands = new Command[7];
offCommands = new Command[7];
Command noCommand = new 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 onButtonWasPressed(int slot){
onCommands[slot].execute();
}
public void onButtonWasPushed(int slot){
offCommands[slot].execute();
}
public String toString(){
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n------Remote Control-------\n");
for (int i = 0; i < onCommands.length; i++) {
stringBuffer.append("[slot " + i + "]" + onCommands[i].getClass().getName() + " " +
offCommands[i].getClass().getName() + "\n");
}
return stringBuffer.toString();
}
}
class RemoteLoader{
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
Light livingRoomLight = new Light("Living Rommt");
Light kitchenLight = new Light("Kitchen");
LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight);
LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);
remoteControl.setCommand(0,livingRoomLightOn,livingRoomLightOff);
remoteControl.setCommand(1,kitchenLightOn,kitchenLightOff);
remoteControl.onButtonWasPressed(0);
remoteControl.onButtonWasPushed(0);
remoteControl.onButtonWasPressed(1);
remoteControl.onButtonWasPushed(1);
}
}
给遥控器加上撤销/返回上一步功能:
/**
* 加上撤销功能
*/
public interface Command {
void execute();
void undo();
}
/**
* NoCommand表示空的命令,什么也不做即可。
*/
class NoCommand implements Command {
@Override
public void execute() {
System.out.println("do nothing");
}
@Override
public void undo() {
System.out.println("do nothing");
}
}
class Light{
private String name;
public Light(String name) {
this.name = name;
}
public void on(){
System.out.println(name + "电灯打开");
}
public void off(){
System.out.println(name + "电灯关闭");
}
}
class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
class RemoteControl{
Command[] onCommands,offCommands;
Command undoCommand; //记录撤销之前的命令
RemoteControl(){
onCommands = new Command[7];
offCommands = new Command[7];
Command noCommand = new NoCommand();
for (int i = 0; i < 7; i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
undoCommand = noCommand;
}
public void setCommand(int slot, Command onCommand, Command offCommand){
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPressed(int slot){
onCommands[slot].execute();
undoCommand = onCommands[slot];
}
public void onButtonWasPushed(int slot){
offCommands[slot].execute();
undoCommand = offCommands[slot];
}
public void undoButtonWasPushed(){
undoCommand.undo();
}
public String toString(){
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n------Remote Control-------\n");
for (int i = 0; i < onCommands.length; i++) {
stringBuffer.append("[slot " + i + "]" + onCommands[i].getClass().getName() + " " +
offCommands[i].getClass().getName() + "\n");
}
return stringBuffer.toString();
}
}
class RemoteLoader{
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
Light livingRoomLight = new Light("Living Rommt");
Light kitchenLight = new Light("Kitchen");
LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight);
LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);
remoteControl.setCommand(0,livingRoomLightOn,livingRoomLightOff);
remoteControl.setCommand(1,kitchenLightOn,kitchenLightOff);
remoteControl.onButtonWasPressed(0);
remoteControl.onButtonWasPushed(0);
remoteControl.undoButtonWasPushed();
remoteControl.onButtonWasPressed(1);
remoteControl.onButtonWasPushed(1);
remoteControl.undoButtonWasPushed();
}
}