命令(Command)模式“请求”封装成对象,以便使用不同的请求队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

直接用一个例子来加以说明: 该代码模拟了一个智能家居遥控器,这个遥控器有七个可编程的插槽(每个插槽对应一个不同的家电装置),每个插槽都有一对相对应的开/关按钮,这个遥控器还有一个整体的撤销按钮。遥控器应该知道如何解读按钮被按下的动作,然后向家电发出正确的请求,但是遥控器不需知道这些家电自动化的细节,或者如何打开热水器。

命令模式可将“动作的请求者”从“动作的执行者”对象中解耦,在设计中采用“命令对象”,把请求(例如打开电灯)封装成一个特定对象(例如客厅电灯对象)。如果对每个按钮都存储一个命令对象,那么当按钮被按下的时候,就可以请命令对象做相关的工作。遥控器并不需要知道工作内容是什么,只要有个命令对象能和正确的对象沟通,把事情做好就可以了,这样一来,遥控器(即发出请求的对象,Invoker)各个家电对象(即接受与执行这些请求的对象,Receiver)就解耦了。

命令模式的类图为

下面直接来看代码

命令接口

public interface Command {public void execute();public void undo();
}

实现一个打开电灯的命令

import com.crow.Receiver.Light;public class LightOnCommand implements Command {Light light;public LightOnCommand(Light light) {this.light = light;}public void execute() {light.on();}public void undo() {light.off();}
}

电灯类:

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;}
}

命令的请求者:遥控器,其中还实现了一键撤销按钮undo

import com.crow.Command.Command;
import com.crow.Command.NoCommand;//
// This is the invoker
//
public class RemoteControl {Command[] onCommands;Command[] offCommands;Command undoCommand;public RemoteControl() {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;}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();}
}

此外,还有一个宏命令类,其中用命令数组存储一大堆命令,可以一次性实施和撤销多个命令。

public class MacroCommand implements Command {Command[] commands;public MacroCommand(Command[] commands) {this.commands = commands;}public void execute() {for (int i = 0; i < commands.length; i++) {commands[i].execute();}}/** * NOTE: these commands have to be done backwards to ensure proper undo functionality */public void undo() {for (int i = commands.length -1; i >= 0; i--) {commands[i].undo();}}
}

应用

  • 日志请求: 当我们执行命令的时候,将历史记录储存在磁盘中,一旦系统死机,我们就可以将命令对象重新加载,并成批地依次调用这些对象的execute()方法,通过使用记录日志,我们可以将上次checkpoint之后的所有操作记录下来,如果系统出状况,从checkpoint开始恢复这些操作。
  • 事务(transaction)处理 使用宏命令,我们可以一次完成或撤销一组操作,这样一来,一整群操作必须全部进行完成,或者没有进行任何的操作,这就实现了事务处理的原理

设计模式(6)——命令模式相关推荐

  1. 设计模式 之 命令模式

    2019独角兽企业重金招聘Python工程师标准>>> 设计模式 之 命令模式 命令模式比较简单,不过多赘述 为什么需要命令模式 将"行为请求者"与"行 ...

  2. 乐在其中设计模式(C#) - 命令模式(Command Pattern)

    原文:乐在其中设计模式(C#) - 命令模式(Command Pattern) [索引页] [源码下载] 乐在其中设计模式(C#) - 命令模式(Command Pattern) 作者:webabcd ...

  3. 23种设计模式之命令模式和策略模式的区别

    文章目录 概述 命令模式 策略模式 相同点 总结 概述 命令模式和策略模式确实很相似,只是命令模式多了一个接收者(Receiver)角色.它们虽然同为行为类模式,但是两者的区别还是很明显的.策略模式的 ...

  4. 设计模式之命令模式(Command)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  5. plsql执行command命令控制台出现乱码_设计模式系列 — 命令模式

    点赞再看,养成习惯,公众号搜一搜[一角钱技术]关注更多原创技术文章.本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章. 前言 23种设计模式速记 单例(sin ...

  6. 设计模式复习-命令模式

    #pragma once #include "stdafx.h" #include<set> #include<string> #include<io ...

  7. Java 设计模式之命令模式

    一.了解命令模式 1.1 什么是命令模式 命令模式将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作.这种说法比较难以理解,换种说法 ...

  8. 设计模式:命令模式(Command)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  9. 【设计模式】命令模式

    命令模式:将请求封装在对象中,客户不直接调用某个对象的方法,而是使用命令,将命令传递给拥有方法的对象从而让某一方法被调用.UML图例如以下: 以下是用C++描写的命令模式的一个简单样例: #inclu ...

  10. Android设计模式之——命令模式

    一.介绍 命令模式(Command Pattern),是行为型设计模式之一.命令模式相对于其他的设计模式来说并没有那么多的条条框框,其实它不是一个很"规范"的模式,不过,就是基于这 ...

最新文章

  1. 测试进度需要考虑的问题
  2. python微信好友分析源代码_搞事情了 | 教你用Python分析微信好友信息(内附完整代码)...
  3. mysql连接参数配置
  4. SPC软件:全程监控食品质量
  5. selenium+ocr 破解验证码
  6. 服务器硬件上架安装步骤,一般服务器上架步骤;
  7. Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级
  8. 瑜伽形体棍出口欧盟CE认证,出口美国CPC认证标准介绍
  9. dataTable显示序号
  10. 网站所在服务器查询方法
  11. 服务器里全是vmx文件,ESXi 虚拟机 提示 无法打开本地虚拟机的 xxx.vmx 的本地管道的 问题解决....
  12. 怎么保证自动化脚本没有问题_质量保证将使设计变得自动化
  13. VTM10.0代码学习5:coding_unit()cu_pred_data()
  14. postgresql表复制
  15. Manifest merger failed with multiple errors, see logs问题处理
  16. ansys与solidworks关联失败_SolidWorks与ANSYS之间的数据交换方法研究
  17. PHP设计模式之中介者模式(Mediator Pattern)了解下
  18. 银行数字化转型开年布局,金融级架构面临的6大挑战和应对思路
  19. Tencent QQ皮肤图像文件格式Gft转png或bmp源代码
  20. 结构体的浅拷贝与深拷贝

热门文章

  1. 2. JavaScript Boolean 对象
  2. VB.NET DataGridView与数据库的连接
  3. 微星msi B450M+i5-8500+1060成功黑苹果
  4. setTimeout 带参数调用问题
  5. [转] TextField的restrict属性妙用
  6. MySQL中使用SQL语句对字段进行重命名
  7. 借助Sigar API获取磁盘信息
  8. Ant—如何Windows操作系统中搭建Apache Ant环境
  9. Java对数组的操作(二)—集合与数组的切换
  10. activity(工作流)初步学习记录