命令模式(Command Pattern) – 设计模式之行为模式:
目录
命令模式(Command Pattern)
定义: Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
注意:
敏捷开发原则告诉我们: 不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不需要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
类图
命令模式通用类图:
例子-开关:
过程:
在生活中,很多会用到小米系列的东西。小米遥控器可以开电灯,风扇,电视,空调等,甚至可以语音让小爱同学操作。
类图:
代码:
接口 SwitchCommand
public interface SwitchCommand {
void on(); // 打开
void off();// 关闭
}
灯泡 Bulb
public class Bulb implements SwitchCommand {
@Override
public void on() {
System.out.println("打开电灯,一会儿亮起。");
}
@Override
public void off() {
System.out.println("关闭电灯,变得一片漆黑。");
}
}
电风扇 ElectricFan
public class ElectricFan implements SwitchCommand {
@Override
public void on() {
System.out.println("打开电风扇,风扇转动。");
}
@Override
public void off() {
System.out.println("关闭电风扇,风扇慢慢停止。");
}
}
电视 Television
public class Television implements SwitchCommand {
@Override
public void on() {
System.out.println("打开电视,屏幕亮起。");
}
@Override
public void off() {
System.out.println("关闭电视。");
}
}
调用 SwitchInvoke
public class SwitchInvoke {
private SwitchCommand switchCommand;
// 替换电器
public void setSwitchCommand(SwitchCommand switchCommand) {
this.switchCommand = switchCommand;
}
public void buttonOnClick() {
System.out.println("打开开关");
switchCommand.on();
}
public void buttonOffClick() {
System.out.println("关闭开关");
switchCommand.off();
}
}
测试:
public class SwitchCommandTest {
public static void main(String[] args) {
SwitchInvoke switchInvoke = new SwitchInvoke();
System.out.println("======操作电视======");
switchInvoke.setSwitchCommand(new Television());
switchInvoke.buttonOnClick();
switchInvoke.buttonOffClick();
System.out.println("======操作灯泡======");
switchInvoke.setSwitchCommand(new Bulb());
switchInvoke.buttonOnClick();
switchInvoke.buttonOffClick();
System.out.println("======操作风扇======");
switchInvoke.setSwitchCommand(new ElectricFan());
switchInvoke.buttonOnClick();
switchInvoke.buttonOffClick();
}
}
结果:
======操作电视======
打开开关
打开电视,屏幕亮起。
关闭开关
关闭电视。
======操作灯泡======
打开开关
打开电灯,一会儿亮起。
关闭开关
关闭电灯,变得一片漆黑。
======操作风扇======
打开开关
打开电风扇,风扇转动。
关闭开关
关闭电风扇,风扇慢慢停止。
分析
在调用类SwitchInvoke,声明了命令接口,这样切换电器就可以操作实现了改命令接口的电器了。例子中没有reveive类,因为只有开关的操作。当然除了开关还有很多的操作,再细分具体的命令,这时候改怎么做呢?看另外一篇命令模式实例
总结:
优点:
1、降低了系统耦合度。
2、新的命令可以很容易添加到系统中去。
缺点: 使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景
只要认为是命令的地方就可以采用命令模式,例如,在GUI开发中,一个按钮的点击是一个命令,可以采用命令模式;模拟DOS命令的时候,当然也要采用命令模式;触发-反馈机制的处理等。