设计模式之09命令模式(笔记)
2012-05-16 23:16
369 查看
1 定义:
1.1 定义:Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能)。
1.2 通用类图:
个人认为以下类图更利于理解:
类图中包含的Client从来不是用作测试的,这里的client是为了将“请求”与“执行者”对应起来,若使用此模式,则可以依次准备好:Receiver、Command、Invoker,最后直接调用Invoker的方法。所以这里,为便于理解,将其类图作以细化。
1.3 通用代码:
注意上述client的静态main方法为人为添加的测试,非原模式的一部分。
2 优点
2.1 类间解耦:调用者与接收者角色之间没有任何依赖关系,调用者实现功能时只须调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
2.2 可扩展性:Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
3 缺点
如果命令多,Command的子类就多,这个类会膨胀很大,需慎用。
4 应用场景
触发-反馈机制处理的场所。
5 注意事项
6 扩展
6.1 撤销-重做:这种涉及状态改变的情况,可以有以下两种方法解决。
A:结合备忘录模式还原最后状态,该方法适合接收者为状态的变更情况,而不适合事件处理。
B:通过增加一个新的命令,实现事件的回滚。
6.2 对于接收者不多的情形下,我们可以适当地将某一接收者作为默认参数,实在需要改变接收者时再重新设置。这样可以减少高层模块对低层模块的依赖关系,提高系统的稳定性。
7 范例
7.1撤销-重做(仅支持单步撤销的计算数字的例子)
类图如下:
源代码如下:
结果如下:
清除并设置值: 5
----------------------------------------------
5 + 5 = 10
----------------------------------------------
10 - 5 = 5
----------------------------------------------
撤销上步操作后值: 10
----------------------------------------------
10 x 5 = 50
----------------------------------------------
50 / 5 = 10
----------------------------------------------
1.1 定义:Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能)。
1.2 通用类图:
个人认为以下类图更利于理解:
类图中包含的Client从来不是用作测试的,这里的client是为了将“请求”与“执行者”对应起来,若使用此模式,则可以依次准备好:Receiver、Command、Invoker,最后直接调用Invoker的方法。所以这里,为便于理解,将其类图作以细化。
1.3 通用代码:
注意上述client的静态main方法为人为添加的测试,非原模式的一部分。
public abstract class Receiver { // 抽象接收者,定义每个接收者都必须完成的业务 public abstract void action(); } public class ConcreteReceiver1 extends Receiver { // 每个接受者都必须处理一定的业务逻辑 public void action() { } } public abstract class Command { // 每个命令类都必须有一个执行命令的方法 public abstract void execute(); } public class ConcreteCommand1 extends Command { // 也对那个Receiver类进行命令处理 private Receiver receiver; // 构造函数传递接收者 public ConcreteCommand1(Receiver _receiver) { this.receiver = _receiver; } // 每个具体的命令都必须实现一个命令 public void execute() { // 业务处理 this.receiver.action(); } } public class Invoker { private Command command; // 受气包,接受命令 public void setCommand(Command _command) { this.command = _command; } // 执行命令 public void doSomething() { this.command.execute(); } } public class Client { public static Command prepareCommand() { // 定义接收者 Receiver receiver = new ConcreteReceiver1(); // 定义一个发送给接收者的命令 Command command = new ConcreteCommand1(receiver); return command; } public static void main(String[] args) { // 首先声明出调用者Invoker Invoker invoker = new Invoker(); // 把命令交给调用者去执行 invoker.setCommand(prepareCommand()); invoker.doSomething(); } }
2 优点
2.1 类间解耦:调用者与接收者角色之间没有任何依赖关系,调用者实现功能时只须调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
2.2 可扩展性:Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
3 缺点
如果命令多,Command的子类就多,这个类会膨胀很大,需慎用。
4 应用场景
触发-反馈机制处理的场所。
5 注意事项
6 扩展
6.1 撤销-重做:这种涉及状态改变的情况,可以有以下两种方法解决。
A:结合备忘录模式还原最后状态,该方法适合接收者为状态的变更情况,而不适合事件处理。
B:通过增加一个新的命令,实现事件的回滚。
6.2 对于接收者不多的情形下,我们可以适当地将某一接收者作为默认参数,实在需要改变接收者时再重新设置。这样可以减少高层模块对低层模块的依赖关系,提高系统的稳定性。
7 范例
7.1撤销-重做(仅支持单步撤销的计算数字的例子)
类图如下:
源代码如下:
package _09_Command.example; public abstract class Command { Receiver receiver; int parm; public Command(Receiver rec, int parm) { this.receiver = rec; this.parm = parm; } public abstract void execute(); } public class AddCommand extends Command { public AddCommand(Receiver rec, int parm) { super(rec, parm); } @Override public void execute() { receiver.action(CMD.ADD, parm); } } public class SubCommand extends Command { public SubCommand(Receiver rec, int parm) { super(rec, parm); } @Override public void execute() { receiver.action(CMD.SUB, parm); } } public class MulCommand extends Command { public MulCommand(Receiver rec, int parm) { super(rec, parm); } @Override public void execute() { receiver.action(CMD.MUL, parm); } } public class DivCommand extends Command { public DivCommand(Receiver rec, int parm) { super(rec, parm); } @Override public void execute() { receiver.action(CMD.DIV, parm); } } public class SetCommand extends Command { public SetCommand(Receiver rec, int parm) { super(rec, parm); } @Override public void execute() { receiver.action(CMD.SET, parm); } } public class UndoCommand extends Command { public UndoCommand(Receiver rec, int parm) { super(rec, 0); } @Override public void execute() { receiver.action(CMD.UNDO, 0); } } enum CMD { ADD, SUB, MUL, DIV, SET, UNDO }; public abstract class Receiver { protected int result = 0; protected int lastParm; protected CMD lastAction; public abstract void action(CMD cmd, int parm); } public class ConcreteReceiver extends Receiver { @Override public void action(CMD cmd, int parm) { switch (cmd) { case ADD: System.out.print(result + " + " + parm + " = "); result += parm; lastParm = parm; lastAction = CMD.ADD; System.out.println(result); System.out .println("----------------------------------------------"); break; case SUB: System.out.print(result + " - " + parm + " = "); result -= parm; lastParm = parm; lastAction = CMD.SUB; System.out.println(result); System.out .println("----------------------------------------------"); break; case MUL: System.out.print(result + " x " + parm + " = "); result *= parm; lastParm = parm; lastAction = CMD.MUL; System.out.println(result); System.out .println("----------------------------------------------"); break; case DIV: System.out.print(result + " / " + parm + " = "); result /= parm; lastParm = parm; lastAction = CMD.DIV; System.out.println(result); System.out .println("----------------------------------------------"); break; case SET: result = parm; lastParm = 0; lastAction = CMD.SET; System.out.println("清除并设置值: " + result); System.out .println("----------------------------------------------"); break; case UNDO: if (lastAction != CMD.UNDO && lastAction != CMD.SET) { switch (lastAction) { case ADD: result -= lastParm; break; case SUB: result += lastParm; break; case MUL: result /= lastParm; break; case DIV: result *= lastParm; break; } lastAction = CMD.UNDO; System.out.println("撤销上步操作后值: " + result); System.out .println("----------------------------------------------"); } break; } } } public class Invoker { Command command; public void action() { command.execute(); } public void setCommand(Command cmd) { command = cmd; } } public class Client { public static void main(String[] args) {// // just for test Receiver rec = new ConcreteReceiver(); Command cmds[] = { new SetCommand(rec, 5), new AddCommand(rec, 5), new SubCommand(rec, 5), new UndoCommand(rec, 5), new MulCommand(rec, 5), new DivCommand(rec, 5) }; Invoker inv = new Invoker(); for (int i = 0; i < 6; i++) { inv.setCommand(cmds[i]); inv.action(); } } }
结果如下:
清除并设置值: 5
----------------------------------------------
5 + 5 = 10
----------------------------------------------
10 - 5 = 5
----------------------------------------------
撤销上步操作后值: 10
----------------------------------------------
10 x 5 = 50
----------------------------------------------
50 / 5 = 10
----------------------------------------------
相关文章推荐
- 【学习笔记】设计模式-命令模式
- 设计模式笔记之命令模式(command Pattern)
- 设计模式学习笔记(十六)——Command命令
- Java-马士兵设计模式学习笔记-命令模式
- 【设计模式】学习笔记8:命令模式(Command)
- 设计模式学习笔记(一:命令模式)
- 设计模式学习笔记——命令模式
- 【学习笔记javascript设计模式与开发实践(命令模式)----9】
- 学习笔记:java设计模式--命令模式
- 设计模式C++学习笔记之十二(Command命令模式)
- 步步为营 .NET 设计模式学习笔记 九、Command(命令模式)
- 设计模式学习笔记之命令模式
- 设计模式学习笔记(十七)——Command命令模式
- [设计模式笔记]三. 行为型模式--16. Command模式(命令模式)(一)
- 设计模式笔记--命令模式
- 设计模式笔记(15)---命令模式(行为型)
- Java设计模式笔记之命令模式
- 设计模式之禅学习笔记--命令模式
- 设计模式学习笔记(十七)——Command命令模式
- 设计模式C++学习笔记之十二(Command命令模式)