设计模式六:用一个遥控开关的例子说清楚命令模式
原创
©著作权归作者所有:来自51CTO博客作者zhuhuix的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
设计模式一:
《用一个营销策略的实例说清楚策略模式的应用场景》
设计模式二:
《用一个股票买卖的例子说清楚观察者模式》
设计模式三:
《用一个苏式面条的实例说清楚装饰者模式》
设计模式四:
《用一个生产手机的简单例子说清楚工厂模式》
设计模式五:
《用不同的实现方式创建单例模式》
一、背景
- 对于设计模式的理解,最关键的是要确定运用的场景,比如今天我们要学习的命令模式 ,需要把特命令包裹在对象中,并将其做特有的封装并传给请求者,实现命令请求者与命令实现者的解耦。
- 本文将通过一键遥控开关的例子彻底认清楚命令模式长什么样。
二、场景模拟
- 假设现在有个小居室,室内分为卧室、客厅、餐厅、厨房等各个房间
- 主人晚上每天回家后有个习惯,需要将卧室、客厅、餐厅等房间的灯依次打开
- 我们首先用传统的模式来模拟以上这些情景:
- 创建一个电灯类,电灯有开和关两个命令,可以通过这两个操作打开和关闭灯开。
/**
* 电灯类
*/
public class Light {
private String name;
public Light(String name) {
this.name = name;
}
public void on(){
System.out.println("打开"+name+"电灯");
}
public void off(){
System.out.println("关闭"+name+"电灯");
}
}
- 模拟主人回家依次打开卧室、客厅、餐厅的灯,在睡觉时依次关闭
/**
* 模拟主人打开及关闭灯光
*/
public class Client {
public static void main(String[] args) {
System.out.println("依次打开灯光:======================");
// 找到卧室电灯并打开
Light light1 = new Light("卧室");
light1.on();
// 找到客厅电灯并打开
Light light2 = new Light("客厅");
light2.on();
// 找到餐厅电灯并打开
Light light3 = new Light("餐厅");
light3.on();
System.out.println("睡觉依次关闭灯光:======================");
light2.off();
light3.off();
light1.off();
}
}
三、用命令模式设计一个遥控开关
- 是不是觉得很麻烦?主人回家时首先需要进到各个房间,依次打开各个开关,然后睡觉前再要确认灯光是否关闭。
- 这时候,主人提出来这样一个需求,给各个房间的灯光控制设置一个遥控开关,可以通过遥控进行开关,并且这个遥控器上需要设计一键开或关的功能。
- 针对以上需求,我们用命令模式来进行设计:首先将灯开开关命令包裹在特定的对象中
/**
* 开关命令接口
*/
public interface Command {
void execute();
}
/**
* 打开灯光命令
*/
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
/**
* 打开灯光命令
*/
public class LightOffCommand implements Command{
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
- 设置一个遥控器,并且在这个遥控器放上一键开和一键关的快捷按钮
/**
* 遥控器:将各个地方的电灯集中到遥控器上,并可一键控制
*/
public class RemoteControl {
List<Command> turnOnCommands= new ArrayList<>();
List<Command> turnOffCommands= new ArrayList<>();
public RemoteControl() {
Light light1 = new Light("卧室");
LightOnCommand light1OnCommand = new LightOnCommand(light1);
turnOnCommands.add(light1OnCommand);
LightOffCommand light1OffCommand = new LightOffCommand(light1);
turnOffCommands.add(light1OffCommand);
Light light2 = new Light("客厅");
LightOnCommand light2OnCommand = new LightOnCommand(light2);
turnOnCommands.add(light2OnCommand);
LightOffCommand light2OffCommand = new LightOffCommand(light2);
turnOffCommands.add(light2OffCommand);
Light light3 = new Light("餐厅");
LightOnCommand light3OnCommand = new LightOnCommand(light3);
turnOnCommands.add(light3OnCommand);
LightOffCommand light3OffCommand = new LightOffCommand(light3);
turnOffCommands.add(light3OffCommand);
}
// 一键开
public void turnOn(){
for(Command command : turnOnCommands){
command.execute();
}
}
// 一键关
public void turnOff(){
for(Command command : turnOffCommands){
command.execute();
}
}
}
- 让主人使用这个遥控器:
/**
* 主人一键开关电灯
*/
public class Client {
public static void main(String[] args) {
// 找到遥控器
RemoteControl remoteControl = new RemoteControl();
System.out.println("一键遥控打开灯光:======================");
remoteControl.turnOn();
System.out.println("一键遥控关闭灯光:======================");
remoteControl.turnOff();
}
}
四、总结
- LigntOnCommand和LigntOnCommand实现了命令模式统一的接口,把开关灯的特定命令进行抽离
- RemoteControl遥控器相当于是一个代理类,把居室房间内的开关命令都集成到了该类中
- 主人只需要使用这个代理类请求开或关的命令让电灯执行对应的命令即可