命令模式(Command Pattern)属于行为型模式的一种,又称为行动(Action)模式或交易(Transaction)模式。将一个请求封装为一个对象,从而达到用不同的请求对客户进行参数化,对于排队请求或请求日志记录,可以提供命令的撤销和恢复功能。

<!-- more -->

概述

命令模式:对命令的封装,把发送命令和执行命令的责任分割开,分别委派给不同的对象,每一个命令都是一个操作,允许请求方与接收方独立开来,使之请求方不必清楚接收方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。

UML结构图

模式结构

  • Command(抽象命令类): 声明了用于执行请求的的exceute()等方法
  • ConcreteCommand(具体命令类): 抽象命令类的子类,对应具体的接收者对象,将接收者对象的动作绑定其中。在实现execute()方

法时,将调用接收者对象的相关操作(Action)。

  • Invoker(调用者): 调用命令对象执行请求,相关的方法叫做行动方法。
  • Receiver(接收者): 负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。

案例

博主比较喜欢听歌,这里就以MusicPlayer(音乐播放器)为案例,一般播放器中都有播放(play)跳过(skip)停止(stop)等功能,是一种比较典型的命令模式

UML图如下:

1.定义Command(抽象命令类),只有一个execute()用来执行命令

interface Command {void execute();
}

2.创建不同指令的ConcreteCommand(具体命令类)

class PlayCommand implements Command {private MusicPlayer musicPlayer;public PlayCommand(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.play();}
}class SkipCommand implements Command {private MusicPlayer musicPlayer;public SkipCommand(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.skip();}
}class StopCommand implements Command {private MusicPlayer musicPlayer;public StopCommand(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.stop();}
}

3.MusicInvoker(调用者),接收客户端发送过来的指令

class MusicInvoker {private Command playCommand;private Command skipCommand;private Command stopCommand;public void setPlayCommand(Command playCommand) {this.playCommand = playCommand;}public void setSkipCommand(Command skipCommand) {this.skipCommand = skipCommand;}public void setStopCommand(Command stopCommand) {this.stopCommand = stopCommand;}public void play() {playCommand.execute();}public void skip() {skipCommand.execute();}public void stop() {stopCommand.execute();}
}

4.MusicPlayer(接收者),执行接收到的指令

class MusicPlayer {public void play() {System.out.println("播放...");}public void skip() {System.out.println("跳过...");}public void stop() {System.out.println("停止...");}
}

5.测试类MusicPlayerClient

public class MusicPlayerClient {public static void main(String[] args) {// 创建 Receiver(接收者)MusicPlayer musicPlayer = new MusicPlayer();// Command(抽象命令类)Command playCommand = new PlayCommand(musicPlayer);Command skipCommand = new SkipCommand(musicPlayer);Command stopCommand = new StopCommand(musicPlayer);// 创建 Invoker(调用者)MusicInvoker invoker = new MusicInvoker();invoker.setPlayCommand(playCommand);invoker.setSkipCommand(skipCommand);invoker.setStopCommand(stopCommand);// 测试invoker.play();invoker.skip();invoker.stop();invoker.play();invoker.stop();}
}

6.运行结果

宏命令

宏命令: 又称为组合命令,组合多个命令,它是命令模式和组合模式联用的产物;

假设MusicPlayer(音乐播放器)有一个记录功能,可以把每一个命令记录下来,在需要的时候又可以将历史记录的命令在执行一遍,这就是所谓的宏命令集功能。

UML图如下:

1.定义MacroCommand(宏命令类),继承基础Command(命令类)

interface MacroCommand extends Command {void add(Command command);void remove(Command command);
}

2.创建MacroMusicCommand实现MacroCommand

class MacroMusicCommand implements MacroCommand {private static final List<Command> COMMANDS = new ArrayList<>();@Overridepublic void execute() {System.out.println("==========回放开始==========");COMMANDS.forEach(Command::execute);System.out.println("==========回放结束==========");}@Overridepublic void add(Command command) {COMMANDS.add(command);}@Overridepublic void remove(Command command) {COMMANDS.remove(command);}
}

3.测试类

public class MusicPlayerClient {public static void main(String[] args) {// 创建 Receiver(接收者)MusicPlayer musicPlayer = new MusicPlayer();// Command(抽象命令类)Command playCommand = new PlayCommand(musicPlayer);Command skipCommand = new SkipCommand(musicPlayer);Command stopCommand = new StopCommand(musicPlayer);// 创建 Invoker(调用者)MacroCommand macroCommand = new MacroMusicCommand();macroCommand.add(playCommand);macroCommand.add(skipCommand);macroCommand.add(stopCommand);// 测试macroCommand.execute();}
}

4.运行结果

JDK中应用

我们平时使用的java.lang.Runnable就是命令模式的经典应用

// 命令类 与 具体命令实现类
Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("关注 battcn 公众号即可免费领取视频");}
};
// Invoker(调用者) 接收命令
Thread thread = new Thread(runnable);
//  调用 start 命令
thread.start();
//   JDK8 简化写法
new Thread(()->System.out.println("关注 battcn 公众号即可免费领取视频")).start();

总结

优点

  • 将行为调用者和各种行为分隔开,降低程序的耦合,便于程序扩展;
  • 将行为的具体实现封装起来,客户端无需关心行为的具体实现;
  • 为多种行为提供统一的调用入口,便于程序对行为的管理和控制;

缺点

  • 使用命令模式,不论命令简单还是复杂,都需要写一个命令类来封装,滥用命令模式会导致系统出现过多的具体命令类;

适用场景

  • 希望将行为请求者和行为实现者解耦,不直接打交道;
  • 希望分离掉行为请求者一部分的责任,行为请求者只需要将命令发给调用者,不再主动的去让行为实现者产生行为,符合单一职责原则;
  • 希望可以控制执行的命令列表,方便记录,撤销/重做以及事务等功能;
  • 希望可以将请求组合使用,即支持宏命令;

说点什么

全文代码:https://gitee.com/battcn/design-pattern/tree/master/Chapter12/battcn-command

  • 个人QQ:1837307557
  • battcn开源群(适合新手):391619659

微信公众号:battcn(欢迎调戏)

福利

关注公众号:battcn,回复springboot即可获得 <Spring Boot从入门到实战 基础实战系列教程全集><2017最新spring boot 外卖实战微信公众平台视频教程>

一起学设计模式 - 命令模式相关推荐

  1. 小菜学设计模式——命令模式

    2019独角兽企业重金招聘Python工程师标准>>> 背景 外面小摊与店面的比较,你就会发现,店面似乎更加容易管理,为什么呢?因为在客户与老板自己新增了很多员工,这些员工各司其职, ...

  2. Python设计模式-命令模式

    Python设计模式-命令模式 代码基于3.5.2,代码如下; #coding:utf-8 #命令模式class barbecuer():def bakeButton(self):print(&quo ...

  3. 设计模式 命令模式 实例_根据您的命令-命令设计模式

    设计模式 命令模式 实例 命令设计模式是一种广为人知的设计模式,属于行为设计模式("四人帮"的一部分). 顾名思义,它与应用程序中的动作和事件有关. 问题陈述: 假设有一个网页将在 ...

  4. C语言设计模式——命令模式

    C语言设计模式--命令模式 好处:让代码清晰明了,容易添加和删除,易维护. 哪些地方会用到命令模式?(列出几个常见的例子) 1.按键处理,每个按键按下得到一个索引(指的就是命令),一个按键对应一个处理 ...

  5. C语言实现设计模式—命令模式

    文章目录 C语言设计模式--命令模式 传统的实现方式如下:(伪代码) 命令模式优化 UML 用例说明 实现流程 command.h command.c main 总结 C语言设计模式--命令模式 好处 ...

  6. 游戏设计模式 - 命令模式在Unity中的应用(C#)

    游戏设计模式 - 命令模式在Unity中的应用(C#) 实测:这是一篇简单易懂的文章-> https://zhuanlan.zhihu.com/p/46937284

  7. C++设计模式——命令模式(command pattern)

    一.原理讲解 别名动作(action),事务(transaction). 1.1意图 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 ...

  8. 游戏设计模式---命令模式

    命令模式 游戏设计模式Design Patterns Revisited 命令模式是我最喜欢的模式之一. 大多数我写的游戏或者别的什么之类的大型程序,都会在某处用到它. 当在正确的地方使用时,它可以将 ...

  9. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...

最新文章

  1. SVM: 实际中使用SVM的一些问题
  2. 分数相同名次排名规则C语言,如何给数据排名(相同分数相同名次)-excel篇
  3. enum和enum class
  4. MongoDB,还有一个角度看数据
  5. Django2.0中URL的路由机制
  6. 设计模式(十)—— 装饰者模式
  7. was控制台的用户和密码怎样加密使用_交换机密码忘记了,怎么办,密码恢复一分钟了解下...
  8. Atitit 四种自动机 fsm pda 目录 1. 自动机可分为有限自动机、后进先出自动机、线性有界自动机、图灵机等几种。它们对语言的识别能力各不相同。 2 1.1. 抽象自动机的理论。 2 1.
  9. nginx-反向代理笔记
  10. 安卓暗黑模式软件_程序员欢呼!微软 GitHub 安卓版 App 发布预览:支持暗黑模式...
  11. 网络速度在线测试软件,在线网速测试(局域网速度测试工具)
  12. 通信电子电路实验(三)——高频电容反馈型LC振荡器的设计与仿真
  13. 硬盘的结构和介绍,硬盘MBR详细介绍(超详细彩图)
  14. Hexo博客使用友盟+CNZZ统计页面访问次数
  15. 软件工程导论第九到十二章章节复习总结附思维导图
  16. ClinkHouse基本使用说明
  17. JAVA-三种注释方式
  18. 【python-opencv】灰度图和彩色图的互相转换
  19. OB数据库大赛初赛总结
  20. sql的update语句 批量更新某字段

热门文章

  1. Linux有时会出现“You have new mail in /var/spool/mail/root”
  2. cocos2d-x学习笔记03:绘制基本图元
  3. Py中的heapq模块【转载】
  4. Hosts文件实际应用 配置内部服务器提高访问效率和速度
  5. 使用python进行utf9编码和解码
  6. 编写线程安全的Java缓存读写机制 (原创)
  7. 程序人生【一些经典的资料】
  8. HTML课堂笔记02-21
  9. 编译器错误信息: CS1595: 已在多处定义“ ”;一种可能出现的情况
  10. 雷霄骅开源视音频项目汇总