Java设计模式-命令模式
在对象的结构和创建问题都解决了之后,就剩下对象的行为问题了: 如果对象的行为设计的好,那么对象的行为就会更清晰,它们之间的协作效率就会提高.
行为型模式共有11个可供研究,它们分别是:命令模式、解释器模式、访问者模式、模板方法模式、观察者模式、状态模式、策略模式、责任链模式、中介者模式、备忘录模式、迭代器模式.
命令模式
命令模式: 又称动作Action模式, 将请求封装为对象, 从而使我们可用不同的请求对客户进行参数化; 命令可用于将行为请求者与行为实现者解耦, 以适应变化(如: 对请求排队、记录日志、支持可撤销操作等).
(图片来源: 设计模式: 可复用面向对象软件的基础)
模式实现
案例:以饭店点菜为例-点餐
客户不需要直接向大厨下达点菜命令, 而是通过给服务员书写菜单, 然后服务员再具体指挥大厨照单做菜, 菜单是一种'Command':
(案例来源: 大话设计模式)
Receiver
命令接收者: 提供很多方法调用, 负责执行与请求相关业务逻辑;
厨师: 只负责做各种各样的菜.
/**
* @author jifang
* @since 16/8/19 上午10:01.
*/
public class CookReceiver {
public void bakeMutton() {
System.out.println("厨师: 烤羊肉串");
}
public void backChickenWing() {
System.out.println("厨师: 烤鸡翅");
}
}
Command
抽象命令接口: 类中对需要执行的操作进行声明, 且包含一个Receiver, 并公布一个execute()方法用来调用Receiver执行命令:
/**
* @author jifang
* @since 16/8/19 上午10:08.
*/
public abstract class Command {
protected CookReceiver receiver;
public Command(CookReceiver receiver) {
this.receiver = receiver;
}
public abstract void execute();
}
ConcreteCommand
具体命令类: 实现Command内的抽象方法(调用Receiver提供的方法).
/**
* 烤肉命令
*/
class BackMuttonCommand extends Command {
public BackMuttonCommand(CookReceiver receiver) {
super(receiver);
}
@Override
public void execute() {
this.receiver.bakeMutton();
}
}
/**
* 烤鸡翅命令
*/
class BackChickenWingCommand extends Command {
public BackChickenWingCommand(CookReceiver receiver) {
super(receiver);
}
@Override
public void execute() {
this.receiver.backChickenWing();
}
}
Invoker
请求的发起者: 内部包含Command聚集, 他通过命令对象来唤起Receiver执行请求. 一个调用者并不需要在设计时确定其接受者, 因此它只与抽象命令Command存在关联.通过调用Command的execute()间接调用Receiver的相关操作:
public class WaiterInvoker {
private Queue<Command> queue = new LinkedList<>();
public void addCommand(Command command) {
if (checkCommand(command)) {
queue.add(command);
}
}
public void cancelCommand(Command command) {
// 如果命令已经执行过, 则不予撤销
if (!queue.isEmpty()) {
queue.remove(command);
}
}
/**
* 通知执行所有命令
*/
public void notifyExecute() {
while (!queue.isEmpty()) {
Command command = queue.poll();
command.execute();
}
}
private boolean checkCommand(Command command) {
// TODO 检查命令是否有效: 如当前原材料是否充足等
return true;
}
}
Client
/**
* Created by jifang on 15/12/3.
*/
public class Client {
@Test
public void client() {
// 开业准备
WaiterInvoker waiter = new WaiterInvoker();
CookReceiver cook = new CookReceiver();
Command backMuttonOrder = new BackMuttonCommand(cook);
Command backChickenWingOrder = new BackChickenWingCommand(cook);
// 接收订单
waiter.addCommand(backMuttonOrder);
waiter.addCommand(backChickenWingOrder);
// 在厨师制作完成之前还可以撤销订单
waiter.cancelCommand(backMuttonOrder);
// 通知执行
waiter.notifyExecute();
}
}
小结:
命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开.
优点
较容易设计一个命令队列;
较容易将命令记录日志;
允许接受请求的一方决定是否要否决请求;
较容易地实现对请求的撤销与重做;
由于添加新的具体命令对其他类没有任何影响, 因此增加新的具体命令很容易;
场景:
Struts2 Action的调用过程;
数据库事务机制;
命令的撤销与恢复.
- IDC发布IT转型报告,现代化、自动化、转型三要素必不可少
- 存储过程和触发器的应用
- 两部委印发车联网产业标准体系建设指南 提到了自动驾驶
- 状态开关按钮ToggleButton
- 微软开放 .NET 框架源代码
- Angularjs基础(十二)
- 妙趣横生的HTML5 Page Visibility API
- 禁止/移除 WordPress 4.2 中前台自动加载的 emjo 脚本
- 项目管理方面的几个.NET开源项目
- 如何向十岁以下的朋友解释编程?这个说法碉堡了!
- 快速比较和合并文件
- 前端页面中 iOS 版微信长按识别二维码的bug 与解决方案
- .NET Mass Downloader -整体下载.NET源码
- Android中Button
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 深入linux下磁盘Disk,分区Partition,挂载Mount
- 净化Git之rebase变基的使用
- Linux内存管理 一个进程究竟占用多少空间?-VSS/RSS/PSS/USS
- Bash:选择结构之case
- ElasticSearch的Reindex
- 10行Python代码自动清理电脑内重复文件,解放双手!
- 【投稿】刀哥:Rust学习笔记 3
- 为你的数据添加置信区间
- Linux磁盘管理
- Vue项目中简单的store模式
- 5分钟学linux命令之split
- 分母为0一定会抛异常吗?
- 明明有class为什么还是报ClassNotFoundException?
- Maven 错误找不到符号
- 环境变量配置为jdk8,却显示java版本为jdk7