23种设计模式之命令模式
来源:互联网 发布:价格水平 知乎 编辑:程序博客网 时间:2024/06/07 01:44
命令模式是行为型设计模式之一。命令模式相对于其他的设计模式来说并没有那么多的条条框框,其实它不是一个很“规矩”的设计模式,就是因为这一点,命令模式相对于其他的设计模式更为灵活多变。
命令模式的定义
将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
命令模式的使用场景
需要抽象出待执行的动作,然后以参数的形式提供出来—类似于过程设计中的回调机制,而命令模式正是回调机制的一个面向对象的替代品。
在不同的时刻指定、排序和执行请求。一个命令对象可以有与初始请求无关的生存期。
需要支持取消操作。
支持修改日志功能,这样当系统崩溃时,这些修改可以被重新做一遍。
需要支持事务操作。
UML类图
由图可以看出命令模式的通用代码:
/** * Created by jmfstart on 2017/6/1. *///接收者类public class Receiver { public void action(){ System.out.println("接受者类执行具体操作"); }}//抽象命令接口public interface Command { void execute();}//具体命令类public class ConcreteCommand implements Command { private Receiver receiver;//持有一个对接收者对象的引用 public ConcreteCommand(Receiver receiver) { this.receiver = receiver; } @Override public void execute() { //调用接收者的相关方法来执行具体逻辑 receiver.action(); }}//请求者类public class Invoker { private Command command; // 持有一个对相应命令对象的引用 public Invoker(Command command) { this.command = command; } public void action(){ // 调用具体命令对象的相关方法,执行具体命令 command.execute(); }}//客户端public class Client { public static void main(String[] args){ //构造一个接收者对象 Receiver receiver = new Receiver(); //根据接收者对象构造一个命令对象 ConcreteCommand command = new ConcreteCommand(receiver); //根据具体的对象构造请求者对象 Invoker invoker = new Invoker(command); // 执行请求方法 invoker.action(); }}
角色介绍:
抽象命令(Command):定义命令的接口,声明执行的方法。
具体命令(ConcreteCommand):具体命令,实现要执行的方法,它通常是“虚”的实现;通常会有接收者,并调用接收者的功能来完成命令要执行的操作。
接收者(Receiver):真正执行命令的对象。任何类都可能成为一个接收者,只要能实现命令要求实现的相应功能。
调用者(Invoker):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
客户端(Client):命令由客户端来创建,并设置命令的接收者。
命令模式代码的简单实现:
//命令者抽象 定义执行方法public interface Command { /** * 执行命令的方法 */ void execute();}//具体命令者 向左、右、掉落、变换public class LeftCommand implements Command { //持有一个接受者俄罗斯方块游戏对象的引用 private TetrisMachine machine; public LeftCommand(TetrisMachine machine) { this.machine = machine; } @Override public void execute() { //调用游戏机里的具体方法执行操作 machine.toLeft(); }}//具体命令者 向左、右、掉落、变换public class RightCommand implements Command { //持有一个接受者俄罗斯方块游戏对象的引用 private TetrisMachine machine; public RightCommand(TetrisMachine machine) { this.machine = machine; } @Override public void execute() { //调用游戏机里的具体方法执行操作 machine.toRight(); }}//具体命令者 向左、右、掉落、变换public class FallCommand implements Command { //持有一个接受者俄罗斯方块游戏对象的引用 private TetrisMachine machine; public FallCommand(TetrisMachine machine) { this.machine = machine; } @Override public void execute() { //调用游戏机里的具体方法执行操作 machine.fastToBottom(); }}//具体命令者 向左、右、掉落、变换public class TransformCommand implements Command { //持有一个接受者俄罗斯方块游戏对象的引用 private TetrisMachine machine; public TransformCommand(TetrisMachine machine) { this.machine = machine; } @Override public void execute() { //调用游戏机里的具体方法执行操作 machine.transform(); }}//请求者类,命令由按钮发起public class Buttons { private LeftCommand leftCommand;// 向左移动的命令对象引用 private RightCommand rightCommand;// 向右移动的命令对引用 private FallCommand fallCommand;// 向下加速的命令对象引用 private TransformCommand transformCommand;// 变换形状的命令对象引用 public void setLeftCommand(LeftCommand leftCommand) { this.leftCommand = leftCommand; } public void setRightCommand(RightCommand rightCommand) { this.rightCommand = rightCommand; } public void setFallCommand(FallCommand fallCommand) { this.fallCommand = fallCommand; } public void setTransformCommand(TransformCommand transformCommand) { this.transformCommand = transformCommand; } /** * 按下按钮向左移动 */ public void toLeft(){ leftCommand.execute(); } /** * 按下按钮向右移动 */ public void toRight(){ rightCommand.execute(); } /** * 按下按钮快速落下 */ public void fall(){ fallCommand.execute(); } /** * 按下按钮改变形状 */ public void transform(){ transformCommand.execute(); }}//客户端public class Player { public static void main(String[] args){ //首先要有俄罗斯方块游戏 TetrisMachine machine = new TetrisMachine(); // 根据游戏我们构造4种命令 LeftCommand leftCommand = new LeftCommand(machine); RightCommand rightCommand = new RightCommand(machine); FallCommand fallCommand = new FallCommand(machine); TransformCommand transformCommand = new TransformCommand(machine); // 按钮可以执行不同的命令 Buttons buttons = new Buttons(); buttons.setLeftCommand(leftCommand); buttons.setRightCommand(rightCommand); buttons.setFallCommand(fallCommand); buttons.setTransformCommand(transformCommand); // 具体按下那个按钮玩家说了算 buttons.toLeft(); buttons.toRight(); buttons.fall(); buttons.transform(); }}
总结
模式分析
本质:对命令进行封装,将发出命令与执行命令的责任分开。
每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。
请求方和接收方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
使请求本身成为一个对象,这个对象和其它对象一样可以被存储和传递。
命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。
优点
解除了请求者与实现者之间的耦合,降低了系统的耦合度。
对请求排队或记录请求日志,支持撤销操作。
可以容易地设计一个组合命令。
新命令可以容易地加入到系统中。
缺点
因为针对每一个命令都需要设计一个具体命令类,使用命令模式可能会导致系统有过多的具体命令类。
- 23种设计模式之命令模式
- 23种设计模式之命令模式
- 23种设计模式之命令模式
- 23设计模式之命令模式(Command)
- 23设计模式之命令模式(Command)
- 23种设计模式之命令模式(Command)
- 23种设计模式之命令模式1
- 23种设计模式之命令模式2
- 23种设计模式之命令模式3
- 23种设计模式之命令模式3
- 23种设计模式之命令模式4
- 23种java设计模式之命令模式
- 23种设计模式C++实例之命令模式
- 23种设计模式之命令(Command)模式
- JAVA开发的23种设计模式之 --- 命令模式
- 设计模式之命令模式
- 设计模式之命令模式
- 设计模式之命令模式
- CSS3-盒子模型box-sizing
- JQuery事件-6.5
- Codeforces Round #417 (Div. 2)
- MindManager优秀导图分享——数学思维导图
- [转]HBase BlockCache机制讲解&源码分析
- 23种设计模式之命令模式
- JQuery效果-6.6
- 动态www服务器的请求流程原理
- JQuey淡入淡出,滑动方法-6.7
- 设计模式详解——迭代器模式
- Hibernate将HQL语句转换成SQL语句
- 需要获得一组具有相同的ID和name的input的几种尝试
- [js点击]JavaScript之Ajax技术01
- 只给出先序遍历和后序遍历不能唯一确定二叉树的例子