一起学设计模式 - 命令模式
命令模式(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 外卖实战微信公众平台视频教程>
一起学设计模式 - 命令模式相关推荐
- 小菜学设计模式——命令模式
2019独角兽企业重金招聘Python工程师标准>>> 背景 外面小摊与店面的比较,你就会发现,店面似乎更加容易管理,为什么呢?因为在客户与老板自己新增了很多员工,这些员工各司其职, ...
- Python设计模式-命令模式
Python设计模式-命令模式 代码基于3.5.2,代码如下; #coding:utf-8 #命令模式class barbecuer():def bakeButton(self):print(&quo ...
- 设计模式 命令模式 实例_根据您的命令-命令设计模式
设计模式 命令模式 实例 命令设计模式是一种广为人知的设计模式,属于行为设计模式("四人帮"的一部分). 顾名思义,它与应用程序中的动作和事件有关. 问题陈述: 假设有一个网页将在 ...
- C语言设计模式——命令模式
C语言设计模式--命令模式 好处:让代码清晰明了,容易添加和删除,易维护. 哪些地方会用到命令模式?(列出几个常见的例子) 1.按键处理,每个按键按下得到一个索引(指的就是命令),一个按键对应一个处理 ...
- C语言实现设计模式—命令模式
文章目录 C语言设计模式--命令模式 传统的实现方式如下:(伪代码) 命令模式优化 UML 用例说明 实现流程 command.h command.c main 总结 C语言设计模式--命令模式 好处 ...
- 游戏设计模式 - 命令模式在Unity中的应用(C#)
游戏设计模式 - 命令模式在Unity中的应用(C#) 实测:这是一篇简单易懂的文章-> https://zhuanlan.zhihu.com/p/46937284
- C++设计模式——命令模式(command pattern)
一.原理讲解 别名动作(action),事务(transaction). 1.1意图 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 ...
- 游戏设计模式---命令模式
命令模式 游戏设计模式Design Patterns Revisited 命令模式是我最喜欢的模式之一. 大多数我写的游戏或者别的什么之类的大型程序,都会在某处用到它. 当在正确的地方使用时,它可以将 ...
- [Head First设计模式]餐馆中的设计模式——命令模式
系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...
最新文章
- SVM: 实际中使用SVM的一些问题
- 分数相同名次排名规则C语言,如何给数据排名(相同分数相同名次)-excel篇
- enum和enum class
- MongoDB,还有一个角度看数据
- Django2.0中URL的路由机制
- 设计模式(十)—— 装饰者模式
- was控制台的用户和密码怎样加密使用_交换机密码忘记了,怎么办,密码恢复一分钟了解下...
- Atitit 四种自动机 fsm pda 目录 1. 自动机可分为有限自动机、后进先出自动机、线性有界自动机、图灵机等几种。它们对语言的识别能力各不相同。	2 1.1. 抽象自动机的理论。	2 1.
- nginx-反向代理笔记
- 安卓暗黑模式软件_程序员欢呼!微软 GitHub 安卓版 App 发布预览:支持暗黑模式...
- 网络速度在线测试软件,在线网速测试(局域网速度测试工具)
- 通信电子电路实验(三)——高频电容反馈型LC振荡器的设计与仿真
- 硬盘的结构和介绍,硬盘MBR详细介绍(超详细彩图)
- Hexo博客使用友盟+CNZZ统计页面访问次数
- 软件工程导论第九到十二章章节复习总结附思维导图
- ClinkHouse基本使用说明
- JAVA-三种注释方式
- 【python-opencv】灰度图和彩色图的互相转换
- OB数据库大赛初赛总结
- sql的update语句 批量更新某字段
热门文章
- Linux有时会出现“You have new mail in /var/spool/mail/root”
- cocos2d-x学习笔记03:绘制基本图元
- Py中的heapq模块【转载】
- Hosts文件实际应用 配置内部服务器提高访问效率和速度
- 使用python进行utf9编码和解码
- 编写线程安全的Java缓存读写机制 (原创)
- 程序人生【一些经典的资料】
- HTML课堂笔记02-21
- 编译器错误信息: CS1595: 已在多处定义“ ”;一种可能出现的情况
- 雷霄骅开源视音频项目汇总