继续设计模式哈,今天带来命令模式,二话不说,先看定义:
定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
这尼玛定义,看得人蛋疼,看不明白要淡定,我稍微简化一下:将请求封装成对象,将动作请求者和动作执行者解耦。好了,直接用例子来说明。
需求:最近智能家电很火热啊,未来尼玛估计冰箱都会用支付宝自动买东西了,,,,假设现在有电视、电脑、电灯等家电,现在需要你做个遥控器控制所有家电的开关,要求做到每个按钮对应的功能供用户个性化,对于新买入家电要有非常强的扩展性。
这个需求一看,尼玛要是没有什么个性化、扩展性还好说啊,直接针对每个遥控器的按钮onClick,然后在里面把代码写死就搞定了,但是个性化怎么整,还要有扩展性。。。
好了,下面命令模式出场,命令模式的核心就是把命令封装成类,对于命令执行者不需要知道现在执行的具体是什么命令。
1、首先看下我们拥有的家电的API:
package com.zhy.pattern.command;
/**
* 门
* @author zhy
*
*/
public class Door
{
public void open()
{
System.out.println("打开门");
}
public void close()
{
System.out.println("关闭门");
}
}
package com.zhy.pattern.command;
/**
* 电灯
* @author zhy
*
*/
public class Light
{
public void on()
{
System.out.println("打开电灯");
}
public void off()
{
System.out.println("关闭电灯");
}
}
package com.zhy.pattern.command;
/**
* 电脑
* @author zhy
*
*/
public class Computer
{
public void on()
{
System.out.println("打开电脑");
}
public void off()
{
System.out.println("关闭电脑");
}
}
看来我们有电灯、电脑、和门,并且开关的接口的设计好了。接下来看如何把命令封装成类:
package com.zhy.pattern.command;
public interface Command
{
public void execute();
}
package com.zhy.pattern.command;
/**
* 关闭电灯的命令
* @author zhy
*
*/
public class LightOffCommond implements Command
{
private Light light ;
public LightOffCommond(Light light)
{
this.light = light;
}
@Override
public void execute()
{
light.off();
}
}
package com.zhy.pattern.command;
/**
* 打开电灯的命令
* @author zhy
*
*/
public class LightOnCommond implements Command
{
private Light light ;
public LightOnCommond(Light light)
{
this.light = light;
}
@Override
public void execute()
{
light.on();
}
}
package com.zhy.pattern.command;
/**
* 开电脑的命令
* @author zhy
*
*/
public class ComputerOnCommond implements Command
{
private Computer computer ;
public ComputerOnCommond( Computer computer)
{
this.computer = computer;
}
@Override
public void execute()
{
computer.on();
}
}
package com.zhy.pattern.command;
/**
* 关电脑的命令
* @author zhy
*
*/
public class ComputerOffCommond implements Command
{
private Computer computer ;
public ComputerOffCommond( Computer computer)
{
this.computer = computer;
}
@Override
public void execute()
{
computer.off();
}
}
好了,不贴那么多了,既然有很多命令,按照设计原则,我们肯定有个超类型的Command,然后各个子类,看我们把每个命令(请求)都封装成类了。接下来看我们的遥控器。
package com.zhy.pattern.command;
/**
* 控制器面板,一共有9个按钮
*
* @author zhy
*
*/
public class ControlPanel
{
private static final int CONTROL_SIZE = 9;
private Command[] commands;
public ControlPanel()
{
commands = new Command[CONTROL_SIZE];
/**
* 初始化所有按钮指向空对象
*/
for (int i = 0; i < CONTROL_SIZE; i++)
{
commands[i] = new NoCommand();
}
}
/**
* 设置每个按钮对应的命令
* @param index
* @param command
*/
public void setCommand(int index, Command command)
{
commands[index] = command;
}
/**
* 模拟点击按钮
* @param index
*/
public void keyPressed(int index)
{
commands[index].execute();
}
}
package com.zhy.pattern.command;
/**
* @author zhy
*
*/
public class NoCommand implements Command
{
@Override
public void execute()
{
}
}
注意看到我们的遥控器有9个按钮,提供了设置每个按钮的功能和点击的方法,还有注意到我们使用了一个NoCommand对象,叫做空对象,这个对象的好处就是,我们不用执行前都判断个if(!=null),并且提供了一致的操作。
最后测试一下代码:
package com.zhy.pattern.command;
public class Test
{
public static void main(String[] args)
{
/**
* 三个家电
*/
Light light = new Light();
Door door = new Door();
Computer computer = new Computer();
/**
* 一个控制器,假设是我们的app主界面
*/
ControlPanel controlPanel = new ControlPanel();
// 为每个按钮设置功能
controlPanel.setCommand(0, new LightOnCommond(light));
controlPanel.setCommand(1, new LightOffCommond(light));
controlPanel.setCommand(2, new ComputerOnCommond(computer));
controlPanel.setCommand(3, new ComputerOffCommond(computer));
controlPanel.setCommand(4, new DoorOnCommond(door));
controlPanel.setCommand(5, new DoorOffCommond(door));
// 模拟点击
controlPanel.keyPressed(0);
controlPanel.keyPressed(2);
controlPanel.keyPressed(3);
controlPanel.keyPressed(4);
controlPanel.keyPressed(5);
controlPanel.keyPressed(8);// 这个没有指定,但是不会出任何问题,我们的NoCommand的功劳
}
}
输出结果:
可以看到任意按钮可以随意配置任何命令,再也不需要尼玛的变一下需求改代码了,随便用户怎么个性化了。其实想白了,这里的设置我们还可以配置到一个配置文件中,完全的解耦有木有。
好了,用户对于这个按钮可能还不是太满意,用户希望夜深人静的时候,能够提供个按钮直接关门、关灯、开电脑,,,,大家懂的,,,我们稍微修改下代码,满足他
定义一个命令,用户干一些列的事,可配置,且与原来的命令保持接口一致:
package com.zhy.pattern.command;
/**
* 定义一个命令,可以干一系列的事情
*
* @author zhy
*
*/
public class QuickCommand implements Command
{
private Command[] commands;
public QuickCommand(Command[] commands)
{
this.commands = commands;
}
@Override
public void execute()
{
for (int i = 0; i < commands.length; i++)
{
commands[i].execute();
}
}
}
好了,已经满足屌丝的需求了。我们测试看看。
// 定义一键搞定模式
QuickCommand quickCommand = new QuickCommand(new Command[] { new DoorOffCommond(door),
new LightOffCommond(light), new ComputerOnCommond(computer) });
System.out.println("****点击一键搞定按钮****");
controlPanel.setCommand(8, quickCommand);
controlPanel.keyPressed(8);
是不是很完美。
最后,继续来谈谈命令模式,命令模式就是把命令封装成对象,然后将动作请求者与动作执行者完全解耦,上例中遥控器的按钮和电器一毛钱关系都没吧。
还记得定义中提到了队列,命令模式如何用于队列呢,比如饭店有很多个点菜的地方,有一个做菜的地方,把点菜看作命令,做菜看作命令执行者,不断有人点菜就相当于把菜加入队列,对于做菜的只管从队列里面取,取一个做一个。
定义中还提到了日志,日志一般用于记录用户行为,或者在异常时恢复时用的,比如每个命令现在包含两个方法,一个执行execute,一个undo(上例中为了方便大家理解,没有写undo),我们可以把用户所有命令调用保存到日志中,比如用户操作不当了,电器异常了,只需要把日志中所有的命令拿出来执行一遍undo就完全恢复了,是吧,就是这么个意思。
好了,各位留个言、点个赞算是对我的支持,多谢大家~
分享到:
相关推荐
摘要:随着物联网技术逐渐进入人们生活,智能家居市场形势一片大好,然而大部分智能家居产品制造商多将重点放在产品功能和外观设计上,表面看是可以做更多事,更随心所欲,实际上是将简单的问题复杂化、智能的问题...
介绍了ZigBee技术,提出了一种基于ARM9芯片与ZigBeeCC2480芯片控制的、应用于家居中的智能无线照明系统。该系统具有上电自组网的功能,用户可以控制协调器通过路由器向该路由器节点上的任意一个终端设备发送信号,...
本系统是一款基于STC89C52的GSM智能家居报警系统,能够实现烟雾报警、温度报警、防盗报警,并采用GSM发送警报信息。 1.GSM手机模块TC35 1.1 TC35特点 TC35是Siemeils公司推出的新-代无线通信GSM模块。自带RS232通讯...
课程设计基于51单片机的智能家居报警器控制系统(温湿度,光照,12864,步进电机,串口)原理图 PCB 仿真 源代码及proteus 软件 1、测量温湿度、光照。 2、设置上下限,过限报警 3、自动模式:可以自动报警,可以...
C560-GPRS-DTU为一款工业级GSM/GPRS DTU,-40 +85工作温度,支持485接口/232接口, 支持透传/宏电协议/桑荣协议,多种模式灵活配置,简单易用,传输稳定可靠,技术支持,可定制修改 广泛运用于智能物联、智能家居、...
本资源为基于DSP的智能物联网家用机器人—内含源码、设计框图 1.室内环境监测与报警功能 可以测量房间的温、湿度信息;通过机器人上安装的气体传感器探测有毒易燃性气体,监测结果可在显示屏上显示,还可以通过手机...
C++基于边缘采集的智能网关系统源码,Modbus和M0模拟两种工业场景,边缘计算处理本地数据,上传到服务器 基础功能 支持家居设备(M0)及工业设备(用modbus slave模拟)数据采集和远程控制\n 提供用户界面操作 网关...
该智能家居解决方案基于新唐M0516+DM9051--SPI+以太网+web完成。 主要硬件: Nuvoton M051 ARM Cortex-M0, 50MHz. DAVICOM DM9051 SPI 介面网络芯片,10/100 Mbps MDI/MDIX 交叉直连自适应。 普通5V 制 220V继电器。 ...
RF-WM-3200B1模块是RF-Star全新推出的一款嵌入式Wi-Fi模块,该模块采用TI最新的SimpleLink Wi-Fi CC...另外模块硬件还包含了陶瓷天线、IPEX座子和天线焊盘等3种天线方式可供选择,支持AT命令模式和串口数据透传模式。
自动抄表 / 管理系统 ( AMR / AMM ) 能够提供双向通信能力 , 使电力公司可以自远程自动的获取精确的计费信息 , 取代了费时、费力且效率低下的人工抄表模式。通过采用 Yitran 的 PLC 或无线 - PLC 混合通讯技术,...
自动抄表 / 管理系统 ( AMR / AMM ) 能够提供双向通信能力 , 使电力公司可以自远程自动的获取精确的计费信息 , 取代了费时、费力且效率低下的人工抄表模式。通过采用 Yitran 的 PLC 或无线 - PLC 混合通讯技术,...
使用事件风暴的实际例子:智能家居 从事件风暴到逻辑模型。 对DDD进行了标准化,并且有材料分享和样例代码分享。 对DDD概念里面的问题域和解决方案域、战略设计、战术设计等容易混淆的概念进行讲解。 DDD的一种详细...
支持多种工作模式,已广泛应用于移动POS终端、金融、供应链自动化、智能化运输、工业自动化、智能建筑、智能家居、消防、公共安全、环境保护、气象、数字化医疗、遥感勘测、军事、空间探索、农业、林业、水务、电力...
它还订阅 MQTT 以侦听命令以执行诸如更改温度或更改模式(加热 vs 冷却 vs 关闭)之类的操作。 它的主要设计是促进 Mitsubishi MAC-568IF-E Wifi 控制器和流行的家庭自动化软件之间的集成,但它并不是该平台或硬件...
尼姆家庭助理 Nim Home Assistant(NimHA)是一个...与小米智能家居设备集成 不断监控您的设备 将命令发送到您的设备,例如在网关上播放声音 自动发现设备 安排自动行动 利用来自不同模块的操作,例如发送邮件,通知
STANDBY电流测试:测量IC处于HALT模式时即每一个接点(PAD)在1态0态或Z态保持不变时的漏电流是否符合最低之规格。  耗电测试:整颗IC的静态耗电与动态耗电。  输入电压测试:测量每个输入接脚...
语音命令动作设计 控制启动播放"待命中",启动马达控制,20秒无任何动作回到休息模式 关闭窗帘播放"窗帘关闭中"->控制马达正转至线性滑轨终点->播放"窗帘已关闭" 全部打开播放"窗帘打开中"->控制马达反转至线性滑轨...