- 一文带你搞懂Java动态代理
- 几分钟带你搞懂策略模式
- 几分钟带你搞懂观察者模式
- 一文彻底搞明白工厂和抽象工厂
- 一文搞明白装饰者模式
- 最全单例模式
- 几段代码搞明白命令模式
- 几段代码搞明白适配器模式
- 一看就懂的外观模式
- 一看就懂的模版方法模式
- 几段代码搞懂迭代器模式
- 一文搞懂明白状态模式
关于命令模式的定义,我就直接引用Head First了:命令模式将“请求”封装成对象,以便使用不同的请求。目的是将发起请求的对象和具体执行处理请求的对象完全解耦,并能灵活扩展具有不同操作的接收者对象。
命令模式
假如我们有一个遥控器可以控制不同硬件设备。如:通过一个按钮来控制智能灯的“开灯”,“关灯”。
这是智能灯的接口。当前只有两个方法,即开灯和关灯操作。
public class Light {
public void on() {
System.out.println("开灯");
}
public void off() {
System.out.println("关灯");
}
}
这是命令对象接口。通过调用命令对象的 execute() 方法,即可执行具体的接收者操作。
public interface Command {
public void execute();
}
这是智能灯命令对象,是 Command 的实现类。我们将开灯的请求进行了封装,这个请求即调用“接收者开灯”这个操作。
public class LightOnCommand implements Command {
private Light mLight;
public LightOnCommand(Light light) {
mLight = light;
}
@Override public void execute() {
mLight.on();
}
}
同样我们将“接收者关灯”这个请求,也封装成对象。
public class LightOffCommand implements Command {
private Light mLight;
public LightOnCommand(Light light) {
mLight = light;
}
@Override public void execute() {
mLight.off();
}
}
假如我们有一个遥控器类,可以通过按钮控制智能灯的“开灯”和“闭灯”,代码见下:
public class Control {
private Command mComBtn;
public void setCommand(Command comBtn) {
mComBtn = comBtn;
}
public void btnWasPressed() {
mComBtn.execute();
}
}
发出请求的对象(Control 类)与接收者(Light)是完全解耦的,两者是通过命令对象(Command实现类)沟通的,命令对象封装了接收者的一组动作,当然可多组,这里即“打开智能灯”,“关闭智能灯”的操作。调用者 Control 可直接通过 execute 方法,可动态指定执行特定接收者命令。 我们来进行下测试:
public class Test {
public static void main(String[] ags) {
Control control = new Control();
Light light = new Light();
// 开灯
control.setCommand(new LightOnCommand(light));
control.execute();
// 关灯
control.setCommand(new LightOffCommand(light));
control.execute();
}
}
也许你会有疑惑,为何不实现一个智能硬件接口 Ihardware呢?让我们的Control 直接持有Ihardware呢,针对上面这个类当然可以的。但是如果我们需要再扩展一个智能空调类 AirCon,甚至更多硬件类呢?
public class AirCon {
public void on();
public void off();
// 独有的调节温度
public void adjustTemperature();
}
这个时候再想想命令模式,是不是更有优势呢?我们只需要将调节温度这个请求封装成对象,而完全不必更改 Control 对象。当然这也会和装饰者模式一样,会造成大量的小类,所以具体的选型需要全方位衡量判断。