命令模式(Command Pattern) 实例
目录
在上一个例子命令模式中,并没有出现类图中Receiver的角色,现在风扇要换挡,电视要换台,加减音量。这时候该怎么做?
思考:
电灯只有两个动作: 开和关
风扇有四个动作: 开、关、加挡和减挡
电视有六个动作: 开、关、加台、减台、加音量和减音量
把命令分成三种,然后加入一个Receiver 去接三种的命令
例子-遥控器:
类图:
代码:
接口 Command
public interface Command {
void exe(); // 执行命令操作
void unexe(); // 反执行命令操作
}
开关 OpenClose
public interface OpenClose {
void on(); // 打开
void off();// 关闭
}
频道切换 ChannelSwitch
public interface ChannelSwitch extends OpenClose {
void channelUp(); // 频道+或是换挡或是切换模式
void channelDown(); // 频道-或是减挡或是切换模式
}
音量 Device 加其他的接口
public interface Device extends OpenClose, ChannelSwitch {
void volumeUp(); // 音量+
void volumeDown(); // 音量-
}
开关命令 SwitchInvoke
public class OpenCloseCommand implements Command {
private Device device;// 此处持有高级设备接口。
public OpenCloseCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.on();// 开机
}
@Override
public void unexe() {
device.off();// 关机
}
}
频道命令 SwitchInvoke
public class ChannelCommand implements Command {
private Device device;
public ChannelCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.channelUp();
}
@Override
public void unexe() {
device.channelDown();
}
}
音量命令 SwitchInvoke
public class VolumeCommand implements Command {
private Device device;
public VolumeCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.volumeUp(); // 调高音量或是温度
}
@Override
public void unexe() {
device.volumeDown(); // 降低音量或是温度
}
}
灯泡 SwitchInvoke
public class Bulb implements Device {
@Override
public void on() {
System.out.println("打开电灯");
}
@Override
public void off() {
System.out.println("关闭电灯");
}
@Override
public void channelUp() {
// 没有这个内容,啥都不做
}
@Override
public void channelDown() {
// 没有这个内容,啥都不做
}
@Override
public void volumeUp() {
// 没有这个内容,啥都不做
}
@Override
public void volumeDown() {
// 没有这个内容,啥都不做
}
}
电风扇 SwitchInvoke
public class ElectricFan implements Device {
@Override
public void on() {
System.out.println("打开电风扇,风扇转动。");
}
@Override
public void off() {
System.out.println("关闭电风扇,风扇慢慢停止。");
}
@Override
public void channelUp() {
System.out.println("加档,风扇加速转动。");
}
@Override
public void channelDown() {
System.out.println("减档,风扇减速转动。");
}
@Override
public void volumeUp() {
// 没有这个内容,啥都不做
}
@Override
public void volumeDown() {
// 没有这个内容,啥都不做
}
}
电视 SwitchInvoke
public class Television implements Device {
@Override
public void on() {
System.out.println("打开电视,屏幕亮起。");
}
@Override
public void off() {
System.out.println("关闭电视。");
}
@Override
public void channelUp() {
System.out.println("电视往上换频道+");
}
@Override
public void channelDown() {
System.out.println("电视往下换频道-");
}
@Override
public void volumeUp() {
System.out.println("电视增加音量+");
}
@Override
public void volumeDown() {
System.out.println("电视降低音量-");
}
}
命令调用 SwitchInvoke
public class SwitchInvoke {
private Command openCloseCommand;
private Command verticalCommand;
private Command horizontalCommand;
public void bindOpenCloseCommand(Command openCloseCommand) {
this.openCloseCommand = openCloseCommand;
}
// 绑定上下方向键命令
public void bindVerticalCommand(Command verticalCommand) {
this.verticalCommand = verticalCommand;
}
// 绑定左右方向键命令
public void bindHorizontalCommand(Command horizontalCommand) {
this.horizontalCommand = horizontalCommand;
}
public void buttonOnClick() {
System.out.println("按下开机键");
openCloseCommand.exe();
}
public void buttonOffClick() {
System.out.println("按下关机键");
openCloseCommand.unexe();
}
public void buttonUpClick() {
System.out.print("按下↑按键……");
verticalCommand.exe();
}
public void buttonDownClick() {
System.out.print("按下↓按键……");
verticalCommand.unexe();
}
public void buttonLeftClick() {
System.out.print("按下←按键……");
horizontalCommand.unexe();
}
public void buttonRightClick() {
System.out.print("单击→按键……");
horizontalCommand.exe();
}
}
测试:
public class DeviceCommandTest {
public static void main(String[] args) {
System.out.println("=========使用遥控器操作电器=========");
Device bulb = new Bulb();
Device electricFan = new ElectricFan();
Device tv = new Television();
SwitchInvoke switchInvoke = new SwitchInvoke();
switchInvoke.bindOpenCloseCommand(new OpenCloseCommand(bulb));
System.out.println("========= 操作电灯 ========");
switchInvoke.buttonOnClick();
switchInvoke.buttonOffClick();
// 绑定 电风扇
switchInvoke.bindOpenCloseCommand(new OpenCloseCommand(electricFan));
switchInvoke.bindVerticalCommand(new ChannelCommand(electricFan));
System.out.println("========= 操作电风扇 ========");
switchInvoke.buttonOnClick();
switchInvoke.buttonUpClick();
switchInvoke.buttonUpClick();
switchInvoke.buttonDownClick();
switchInvoke.buttonOffClick();
//绑定 电视机
switchInvoke.bindOpenCloseCommand(new OpenCloseCommand(tv));
switchInvoke.bindVerticalCommand(new ChannelCommand(tv));
switchInvoke.bindHorizontalCommand(new VolumeCommand(tv));
System.out.println("========= 操作电视 ========");
switchInvoke.buttonOnClick();
switchInvoke.buttonUpClick();
switchInvoke.buttonUpClick();
switchInvoke.buttonDownClick();
switchInvoke.buttonDownClick();
switchInvoke.buttonRightClick();
switchInvoke.buttonLeftClick();
switchInvoke.buttonOffClick();
}
}
结果:
=========使用遥控器操作电器=========
========= 操作电灯 ========
按下开机键
打开电灯
按下关机键
关闭电灯
========= 操作电风扇 ========
按下开机键
打开电风扇,风扇转动。
按下↑按键……加档,风扇加速转动。
按下↑按键……加档,风扇加速转动。
按下↓按键……减档,风扇减速转动。
按下关机键
关闭电风扇,风扇慢慢停止。
========= 操作电视 ========
按下开机键
打开电视,屏幕亮起。
按下↑按键……电视往上换频道+
按下↑按键……电视往上换频道+
按下↓按键……电视往下换频道-
按下↓按键……电视往下换频道-
单击→按键……电视增加音量+
按下←按键……电视降低音量-
按下关机键
关闭电视。
分析
电灯只有两个动作: 开和关
电风扇有四个动作: 开、关、加挡和减挡
电视有六个动作: 开、关、加台、减台、加音量和减音量
为了让控制器统一处理,不得不先电灯和电风扇空实现不需要的接口。我也没有想到更好的方式去处理。后面想到了,再完善补充。
总结:
命令模式感觉在工作中不常用,但是思想不错。统一控制和切换内容。