前言
命令模式(Command Pattern)属于数据驱动当设计模式,是一种行为模式。将请求封装成对象,以便使用不同的请求/队列或日志来参数化其他对象。命令模式也支持可撤销的操作。
当需要将发出请求对象和执行请求对象解耦的时候,使用命令模式。
对行为请求者和行为实现者进行解耦,常用于对行为进行记录、撤销或重做、事务等处理。
命令模式的代码实现
我们以遥控器为例,家里有电扇,灯等家具。我们想要一个遥控就能控制相应等家具那么该如何设计呢?
首先我们创建一个实现命令等接口:
public interface Command {
public void execute();
}
然后,对于打开灯和关闭灯的命令进行封装:
public class Light {
public Light() {
}
public void on() {
System.out.println("Light is on");
}
public void off() {
System.out.println("Light is off");
}
}
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
}
public class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.off();
}
}
那么我们该怎么在遥控器上使用呢?我们定义一个控制类SimpleRemoteControl
public class SimpleRemoteControl {
Command onCommand;
Command offCommand;
public SimpleRemoteControl() {}
public void setCommand(Command onCommand, Command offCommand) {
this.onCommand = onCommand;
this.offCommand = offCommand;
}
public void onButtonWasPressed() {
onCommand.execute();
}
public void offButtonWasPressed() {
offCommand.execute();
}
}
我们可以看到当我们传入相应的Command实现类,按下按钮后会执行execute()方法,然后执行相应的操作。
这里我们可能需要一个撤销的功能,那么,我们在Command接口中加入undo()方法。
public interface Command {
public void execute();
public void undo();
}
那么相应的关灯和开灯的命令类有如下变化:
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
public void undo() {
light.off();
}
}
public class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.off();
}
public void undo() {
light.on();
}
}
这么做看似很简单,但当我们第二次按下但时候,发现并不能做到再次撤销的结果。所以这个时候,我们需要在SimpleRemoteControl类中添加一个记录最后命令的变量。如下所示:
public class SimpleRemoteControl {
private Command onCommand;
private Command offCommand;
private Command undoCommand;
public SimpleRemoteControl() {}
public void setCommand(Command onCommand, Command offCommand) {
this.onCommand = onCommand;
this.offCommand = offCommand;
}
public void onButtonWasPressed() {
onCommand.execute();
undoCommand = onCommand;
}
public void offButtonWasPressed() {
offCommand.execute();
undoCommand = offCommand;
}
public void undoButtonWasPushed() {
if(null != undoCommand) {
undoCommand.undo();
}
}
}
测试类和测试结果如下:
public class RemoteControlTest {
public static void main(String[] args) {
SimpleRemoteControl remote = new SimpleRemoteControl();
Light light = new Light();
LightOnCommand lightOn = new LightOnCommand(light);
LightOffCommand lightOff = new LightOffCommand(light);
remote.setCommand(lightOn,lightOff);
remote.onButtonWasPressed();
remote.undoButtonWasPushed();
remote.offButtonWasPressed();
remote.undoButtonWasPushed();
}
}
Light is on
Light is off
Light is off
Light is on
同理,关于电扇的操作大同小异,由于篇幅问题就不赘述,并且我们还可以针对风扇的速度进行相应的设计。我们可以通过设计不同的具体命令类来实现不同的功能,比如一键开灯,同时关闭所有电器。
相信通过以上的说明,了解了命令模式是如何工作和使用的。同时命令模式具有以下优缺点:
优点: 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。
缺点:使用命令模式可能会导致某些系统有过多的具体命令类。












网友评论