在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。
假设现在我们需要制作一个万能遥控器,去控制日光灯、音响和电视的开关,我们使用遥控器进行开关操作的时候,并不关心遥控器具体请求是哪个,我们只知道要进行开关操作,这时候就可以用命令模式来进行设计。
首先我们先定义命令接口,使所有的命令都继承这个接口,如开灯命令、关灯命令等。

public interface Command { // 命令 public void excute(); }
然后我们定义一个遥控器,它有着开关的功能,也就是两个命令,开启命令和关闭命令。

public class RemoteControl { private Command onCommand; private Command offCommand; public RemoteControl() { this.onCommand = new NoCommd(); this.offCommand = new NoCommd(); } public void setCommand(Command onCommand, Command offCommand) { this.onCommand = onCommand; this.offCommand = offCommand; } public void onButtonWasPushed() { this.onCommand.excute(); } public void offButtonWasPushed() { this.offCommand.excute(); } }
接下来是音响、日光灯、电视机这三个实体类

public class Audio { public void on() { System.out.println("Audio is on!"); } public void off() { System.out.println("Audio is off!"); } } public class Light { public void on() { System.out.println("Light is on!"); } public void off() { System.out.println("Light is off!"); } } public class Television { public void on() { System.out.println("Television is on!"); } public void off() { System.out.println("Television is off!"); } }
然后是实现各个电器开关命令的命令类

public class AudioOffCommand implements Command { private Audio audio; public AudioOffCommand(Audio audio) { this.audio = audio; } @Override public void excute() { audio.off(); } }

public class AudioOnCommand implements Command { private Audio audio; public AudioOnCommand(Audio audio) { this.audio = audio; } @Override public void excute() { audio.on(); } }

public class LightOffCommand implements Command { private Light light; public LightOffCommand(Light light) { this.light = light; } @Override public void excute() { light.off(); } }

public class LightOnCommand implements Command { private Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void excute() { light.on(); } }

public class TelevisionOffCommand implements Command { private Television television; public TelevisionOffCommand(Television television) { this.television = television; } @Override public void excute() { television.off(); } }

public class TelevisionOnCommand implements Command { private Television television; public TelevisionOnCommand(Television television) { this.television = television; } @Override public void excute() { television.on(); } }
测试
public static void main(String[] args) { RemoteControl remoteControl = new RemoteControl(); Light light = new Light(); LightOnCommand lightOnCommand = new LightOnCommand(light); LightOffCommand lightOffCommand = new LightOffCommand(light); System.out.println("使用万能遥控器控制日光灯"); remoteControl.setCommand(lightOnCommand, lightOffCommand); remoteControl.onButtonWasPushed(); remoteControl.offButtonWasPushed(); Audio audio = new Audio(); AudioOnCommand audioOnCommand = new AudioOnCommand(audio); AudioOffCommand audioOffCommand = new AudioOffCommand(audio); System.out.println("使用万能遥控器控制音响"); remoteControl.setCommand(audioOnCommand, audioOffCommand); remoteControl.onButtonWasPushed(); remoteControl.offButtonWasPushed(); Television television = new Television(); TelevisionOnCommand televisionOnCommand = new TelevisionOnCommand(television); TelevisionOffCommand televisionOffCommand = new TelevisionOffCommand(television); System.out.println("使用万能遥控器控制电视"); remoteControl.setCommand(televisionOnCommand, televisionOffCommand); remoteControl.onButtonWasPushed(); remoteControl.offButtonWasPushed(); }
结果
这样就用命令模式实现了万能遥控器的功能。
命令模式将发出请求的万能遥控器和执行请求的对象解耦了,降低了耦合度。新的命令可以很容易地加入到其中,如果需要控制电风扇,只需要创建开启和关闭电风扇的命令,然后绑定到万能遥控器中即可。
但是每个命令都需要创建一个命令对象,这就导致了具体命令类的数量会很多,使用的时候需要谨慎。