《设计模式》之命令模式
一、命令模式定义
命令大家都不会陌生,那么在开始命令模式之前,可以想象一下生活中的命令模式的特点:
如老板命令你完成一个OA项目是一个命令,接着看看其特点:
1、在上面的命令中,命令的执行者肯定是聪明的你了。具体的执行方法,可能是通过vs实现,或者是通过eclipse实现,由此看来:命令要有个命令的执行者,还要有个命令的执行方法。
2、命令的发出者很明显是老板,老板还有个发出方法,可能是通过电话给你说,也可能给你邮件给你说,也可能是通过开会给你说。所以命令的发出者要有一个命令,还要有个发出的方法。
3、最后看看命令,命令有个名字,命令的肯定要执行。而且命令是在boss给你发出通知后执行的。
接下来看看命令模式的定义:
命令模式:将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。
二、问题描述
使用命令模式实现遥控器,遥控器上的不同按钮控制电灯的开关及亮度、天花板风扇的开关及转速等,支持撤销。具体按钮:开灯/关灯按钮、暗光开/关按钮、风扇高速/中速/低速/关按钮、撤销按钮。遥控器如下图所示:
遥控器担当请求者(或称为调用者)的角色,用RemoteControlWithUndo类实现,其内有Command[]类型的属性onCommands和offCommands表示对应的一组开关,Command类型的属性undoCommand记录最后执行的命令用于命令的撤销。遥控器上有7组开关按钮和一个撤销按钮。每个按钮对应一个具体命令,说明如下:
三、类图
四、代码实现
1.命令角色:Command
- public interface Command {
- public void execute();
- public void undo();//实现撤销
- }
2.接收者角色:Light、CeilingFan
(1)Light电灯:
- public class Light {
- String location;
- int level;//灯光的亮度
- public Light(String location) {
- this.location = location;
- }
- public void on() {
- level = 100;
- System.out.println("Light is on");
- }
- public void off() {
- level = 0;
- System.out.println("Light is off");
- }
- //调整灯光的亮度
- public void dim(int level) {
- this.level = level;
- if (level == 0) {
- off();
- }
- else {
- System.out.println("Light is dimmed to " + level + "%");
- }
- }
- //获取灯光的亮度
- public int getLevel() {
- return level;
- }
- }
(2)CeilingFan风扇:
- public class CeilingFan {
- public static final int HIGH = 3;
- public static final int MEDIUM = 2;
- public static final int LOW = 1;
- public static final int OFF = 0;
- String location;//例如卧室、客厅的风扇?
- int speed;
- public CeilingFan(String location) {
- this.location = location;
- speed = OFF;
- }
- public void high() {
- speed = HIGH;
- System.out.println(location + " ceiling fan is on high");
- }
- public void medium() {
- speed = MEDIUM;
- System.out.println(location + " ceiling fan is on medium");
- }
- public void low() {
- speed = LOW;
- System.out.println(location + " ceiling fan is on low");
- }
- public void off() {
- speed = OFF;
- System.out.println(location + " ceiling fan is off");
- }
- public int getSpeed() {
- return speed;
- }
- }
3.具体命令角色:各种命令
(1)NoCommand:空命令,创建遥控器时默认其持有的都是空命令(相比判断null更好),什么事也不做
- public class NoCommand implements Command {
- public void execute() { }
- public void undo() { }
- }
(2)LightOnCommand:开灯命令
- public class LightOnCommand implements Command {
- Light light;
- int level;//level用于记录上次的灯光亮度
- public LightOnCommand(Light light) {
- this.light = light;
- }
- public void execute() {
- level = light.getLevel();
- light.on();
- }
- public void undo() {//将灯光的亮度调到前一次的水平实现撤销
- light.dim(level);
- }
- }
(3)LightOffCommand:关灯命令
- public class LightOffCommand implements Command {
- Light light;
- int level;
- public LightOffCommand(Light light) {
- this.light = light;
- }
- public void execute() {
- level = light.getLevel();
- light.off();
- }
- public void undo() {
- light.dim(level);
- }
- }
(4)DimmerLightOnCommand:开启暗光
- public class DimmerLightOnCommand implements Command {
- Light light;
- int prevLevel;//记录以前的灯光亮度,撤销操作时使用
- public DimmerLightOnCommand(Light light) {
- this.light = light;
- }
- public void execute() {
- prevLevel = light.getLevel();
- light.dim(75);//将灯光亮度调至75%实现暗光
- }
- public void undo() {
- light.dim(prevLevel);
- }
- }
(5)DimmerLightOffCommand:关闭暗光
- public class DimmerLightOffCommand implements Command {
- Light light;
- int prevLevel;
- public DimmerLightOffCommand(Light light) {
- this.light = light;
- prevLevel = 100;
- }
- public void execute() {
- prevLevel = light.getLevel();
- light.off();
- }
- public void undo() {
- light.dim(prevLevel);
- }
- }
(6)CeilingFanHighCommand:风扇高转速
- public class CeilingFanHighCommand implements Command {
- CeilingFan ceilingFan;
- int prevSpeed;//记录以前的转速,用于撤销操作(0时表示以前的状态是:关)
- public CeilingFanHighCommand(CeilingFan ceilingFan) {
- this.ceilingFan = ceilingFan;
- }
- public void execute() {
- prevSpeed = ceilingFan.getSpeed();
- ceilingFan.high();
- }
- public void undo() {
- if (prevSpeed == CeilingFan.HIGH) {
- ceilingFan.high();
- } else if (prevSpeed == CeilingFan.MEDIUM) {
- ceilingFan.medium();
- } else if (prevSpeed == CeilingFan.LOW) {
- ceilingFan.low();
- } else if (prevSpeed == CeilingFan.OFF) {
- ceilingFan.off();
- }
- }
- }
(7)CeilingFanMediumCommand:风扇中转速
- public class CeilingFanMediumCommand implements Command {
- CeilingFan ceilingFan;
- int prevSpeed;
- public CeilingFanMediumCommand(CeilingFan ceilingFan) {
- this.ceilingFan = ceilingFan;
- }
- public void execute() {
- prevSpeed = ceilingFan.getSpeed();
- ceilingFan.medium();//将行为的真正执行委托给接收者,此处即ceilingFan风扇对象
- }
- public void undo() {
- if (prevSpeed == CeilingFan.HIGH) {
- ceilingFan.high();
- } else if (prevSpeed == CeilingFan.MEDIUM) {
- ceilingFan.medium();
- } else if (prevSpeed == CeilingFan.LOW) {
- ceilingFan.low();
- } else if (prevSpeed == CeilingFan.OFF) {
- ceilingFan.off();
- }
- }
- }
(8)CeilingFanLowCommand:风扇低转速
- public class CeilingFanLowCommand implements Command {
- CeilingFan ceilingFan;
- int prevSpeed;
- public CeilingFanLowCommand(CeilingFan ceilingFan) {
- this.ceilingFan = ceilingFan;
- }
- public void execute() {
- prevSpeed = ceilingFan.getSpeed();
- ceilingFan.low();
- }
- public void undo() {
- if (prevSpeed == CeilingFan.HIGH) {
- ceilingFan.high();
- } else if (prevSpeed == CeilingFan.MEDIUM) {
- ceilingFan.medium();
- } else if (prevSpeed == CeilingFan.LOW) {
- ceilingFan.low();
- } else if (prevSpeed == CeilingFan.OFF) {
- ceilingFan.off();
- }
- }
- }
(9)CeilingFanOffCommand:关闭风扇
- public class CeilingFanOffCommand implements Command {
- CeilingFan ceilingFan;
- int prevSpeed;
- public CeilingFanOffCommand(CeilingFan ceilingFan) {
- this.ceilingFan = ceilingFan;
- }
- public void execute() {
- prevSpeed = ceilingFan.getSpeed();
- ceilingFan.off();
- }
- public void undo() {
- if (prevSpeed == CeilingFan.HIGH) {
- ceilingFan.high();
- } else if (prevSpeed == CeilingFan.MEDIUM) {
- ceilingFan.medium();
- } else if (prevSpeed == CeilingFan.LOW) {
- ceilingFan.low();
- } else if (prevSpeed == CeilingFan.OFF) {
- ceilingFan.off();
- }
- }
- }
4.遥控器类,请求者(或调用者)角色,持有多个Command对象
- public class RemoteControlWithUndo {
- Command[] onCommands;//对应多个开按钮
- Command[] offCommands;//对应多个关按钮
- Command undoCommand;//对应撤销按钮
- public RemoteControlWithUndo() {
- onCommands = new Command[7];
- offCommands = new Command[7];
- Command noCommand = new NoCommand();
- for(int i=0;i<7;i++) {
- onCommands[i] = noCommand;//默认赋值为空命令,什么事也不做
- offCommands[i] = noCommand;
- }
- undoCommand = noCommand;
- }
- public void setCommand(int slot, Command onCommand, Command offCommand) {
- onCommands[slot] = onCommand;
- offCommands[slot] = offCommand;
- }
- //当编号为第slot的开On按钮按下时执行命令
- public void onButtonWasPushed(int slot) {
- onCommands[slot].execute();
- undoCommand = onCommands[slot];//记录最后执行的命令
- }
- public void offButtonWasPushed(int slot) {
- offCommands[slot].execute();
- undoCommand = offCommands[slot];
- }
- public void undoButtonWasPushed() {
- undoCommand.undo();
- }
- public String toString() {
- StringBuffer stringBuff = new StringBuffer();
- stringBuff.append("\n------ Remote Control -------\n");
- for (int i = 0; i < onCommands.length; i++) {
- stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()
- + " " + offCommands[i].getClass().getName() + "\n");
- }
- stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n");
- return stringBuff.toString();
- }
- }
5.测试
- public class RemoteLoader {
- public static void main(String[] args) {
- RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();
- Light livingRoomLight = new Light("Living Room");
- LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
- LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
- DimmerLightOnCommand dimmerLightOnCommand=new DimmerLightOnCommand(livingRoomLight);
- DimmerLightOffCommand dimmerLightOffCommand=new DimmerLightOffCommand(livingRoomLight);
- CeilingFan ceilingFan = new CeilingFan("Living Room");
- CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan);
- CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);
- CeilingFanLowCommand ceilingFanLow =new CeilingFanLowCommand(ceilingFan);
- CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
- remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
- remoteControl.setCommand(1, dimmerLightOnCommand, dimmerLightOffCommand);
- remoteControl.setCommand(2, ceilingFanHigh, ceilingFanOff);
- remoteControl.setCommand(3, ceilingFanMedium, ceilingFanOff);
- remoteControl.setCommand(4, ceilingFanLow, ceilingFanOff);
- remoteControl.onButtonWasPushed(1);
- remoteControl.onButtonWasPushed(3);
- remoteControl.onButtonWasPushed(2);
- remoteControl.offButtonWasPushed(3);
- remoteControl.undoButtonWasPushed();
- }
- }
运行结果:
- Light is dimmed to 75%
- Living Room ceiling fan is on medium
- Living Room ceiling fan is on high
- Living Room ceiling fan is off
- Living Room ceiling fan is on high
我们可以很轻松地利用组合模式加入宏命令,还有,正如以上代码所示,命令模式的不足之处就是我们需要维护大量的具体命令类。
转载于:https://my.oschina.net/u/3088173/blog/1021776
《设计模式》之命令模式相关推荐
- java命令_JAVA与模式之命令模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述命令(Command)模式的: 命令模式属于对象的行为模式.命令模式又称为行动(Action)模式或交易(Transaction)模式. ...
- 图解Java设计模式学习笔记——行为型模式(模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式)
一.模板方法模式(模板模式)--钩子方法 1.需求-豆浆制作问题 编写制作豆浆的程序,说明如下: 制作豆浆的流程选材-->添加配料-->浸泡-->放到豆浆机打碎. 通过添加不同的配料 ...
- IOS设计模式之四(备忘录模式,命令模式)
本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq) ...
- 设计模式(模板模式,命令模式,备忘录模式)
目录 模板模式 什么是模板模式? 术语? 什么时候使用模板模式? 模板模式的优点? 模板模式的缺点? 角色? 钩子函数? 注意事项和细节? 什么场景使用模板模式? 案例: 命令模式 什么是命令模式? ...
- 行为型模式:命令模式
LieBrother原文: 行为型模式:命令模式 十一大行为型模式之三:命令模式. 简介 姓名 :命令模式 英文名 :Command Pattern 价值观 :军令如山 个人介绍 : Encapsul ...
- 详解Linux系统Vi 和 Vim中正常模式、编辑模式、命令模式相互转化,以及vim命令使用
详解Linux系统Vi 和 Vim中正常模式.编辑模式.命令模式相互转化 vi 和 vim 的基本介绍 vi 和 vim 的三种常见模式 正常模式 正常模式常用命令 插入模式/编辑模式 命令行模式 v ...
- 设计模式之模板方法模式、策略模式、命令模式、责任链模式、状态模式
前言 本章节给您介绍23种设计模式的行为型模式中的模板方法模式.策略模式.命令模式.责任链模式.状态模式. 如有帮助记得3连 加 关注哦!欢迎品论去留言交流,谢谢阅读! 文章目录 前言 一.模板方法模 ...
- 通过英雄联盟塞拉斯大招学习策略模式和命令模式
通过英雄联盟塞拉斯大招学习策略模式和命令模式 前段时间学习了策略模式,第一时间我就想到了英雄联盟当中的英雄塞拉斯,塞拉斯的大招是整个联盟最特殊的大招之一,他可以偷取别的英雄的大招.后面又学习到了命令模 ...
- java execute 执行成功_【JAVA】设计模式之命令模式(Command模式)的使用分析
命令模式属于23种设计模式中行为模式中的一个,它也是一种简单实用非常普遍的设计模式. 首先看下GOF对命令模式的定义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录 ...
- Java设计模式学习总结(16)——行为型模式之命令模式
命令模式 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式.请求以命令的形式包裹在对象中,并传给调用对象.调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应 ...
最新文章
- 分布式主键解决方案----Twitter 雪花算法的原理(Java 版)
- GMap.net 离线地图问题
- 编程珠玑第八章——分治算法求解数组中的最大的连续和
- 03-CoreData原理
- wxWidgets:wxSplitterWindow类用法
- .NET或将引入类型类和扩展
- oauth2.0 php简化模式,OAuth2.0学习(1-5)授权方式2-简化模式(implicit grant type)
- 【JavaScript】Uncaught TypeError: Illegal invocation
- 从零开始学ios开发(十四):Navigation Controllers and Table Views(上)
- 向Windows 日志管理器写入系统程序日志信息
- 目标检测NMS非极大值抑制及改进
- js 去掉浏览器打印默认的页头页尾和打印背景图片
- mupdf添加图片水印_在博客园里给图片加水印(canvas + drag)
- Mac新手操作指南(三)
- 三、向SpringCloud注册Service服务(Restful服务)
- 使用计算机有关的活动,与计算机有关的传统文化活动策划书
- 内存对齐的规则以及作用 verygood!的一篇文章!
- [指北针分类信息软件 v1.5.2.1] 全自动分类信息软件+高效稳定建立SEO外部链接
- “工作三年,跳槽要求涨薪50%”,合理吗?
- petrel软件中的等值线导出然后加入Geomap4.0中成图/用python处理petrel导出的等值线以便于加入Geomap4.0中
热门文章
- Solace 调整最大连接数
- 第十一天-购物车订单系统的实现
- kotlin中的var和val与编译时常量
- 12.静态路由、静态缺省路由
- 基于Mui与H5+开发webapp的Android原生工程打包步骤(使用新版本5+SDK与Android studio)(部分内容转自dcloud官网)...
- 2005年全国信息学分区联赛模拟赛 猫猫的小鱼 题解
- 图像分割(四)—— Is Space-Time Attention All You Need for Video Understanding?
- 批量html转word 或者 pdf
- 如何把pdf文件放到服务器,将生成的PDF文件存储在服务器上
- 区块链与大数据结合分析