首页 > 代码库 > Command - 命令模式

Command - 命令模式

定义
将一个请求封装为一个对象,实现请求者与实施者的低耦合。

案例
大部分应用都存在很多的菜单和一些操作按钮,但在设计这些菜单和按钮的时候,并不知道它要执行什么样的操作。在设计删除、复制和撤销这些具体实现的时候,也不知道在要什么地方用到,可能是代码里面直接调用,也可能是界面上点击了某个按钮后发生的操作。为了解决菜单和具体操作的这种耦合度,就需要使用Command-命令模式:


菜单类的每一个Item都保存一个Command子类的对象实例,当界面点击的时候,就调用Command的execute()方法,在Command子类的execute()方法里面会直接调用Receiver的action()方法,就执行具体的操作。
  1. class MenuItem {
  2. public:
  3. void setCommand(Command* comand) { m_command = command; }
  4. void onClicked() {
  5. m_command->execute();
  6. }
  7. private:
  8. Command* command;
  9. }
  10. class Command {
  11. public:
  12. virtual void execute();
  13. virtual bool isEnable();
  14. };
  15. class CopyCommand {
  16. public:
  17. virtual void execute() {
  18. m_receiver->action();
  19. }
  20. private:
  21. CopyReceiver* m_receiver;
  22. };
  23. class DeleteCommand {
  24. public:
  25. virtual void execute() {
  26. m_enable = m_receiver->action();
  27. }
  28. bool isEnable() {
  29. return m_enable;
  30. }
  31. private:
  32. DeleteReceiver* m_receiver;
  33. bool m_enable;
  34. };
一个Command对象还可以被不同的Invoker对象保存,用以实现同样的操作:
  1. MenuItem* copyItem = new MenuItem("Copy");
  2. MenuItem* deleteItem = new MenuItem("Delete");
  3. MenuItem* undoItem = new MenuItem("Undo");
  4. Button* copyButton = new Button("Copy");
  5. Button* deleteButton = new Button("Delete");
  6. Button* undoButton = new Button("Undo");
  7. Command* copyCommand = new CopyCommand();
  8. Command* deleteCommand = new DeleteCommand();
  9. Command* undoCommand = new UndoCommand();
  10. copyItem->setCommand(copyCommand);
  11. deleteItem->setCommand(deleteCommand);
  12. undoItem->setCommand(undoCommand);
  13. copyButton->setCommand(copyCommand);
  14. deleteButton->setCommand(deleteCommand);
  15. undoButton->setCommand(undoCommand);


相同的操作都使用同一个对象,当undoCommond的enable()返回false的时候,菜单和按钮都不能使用了。

适用性
  • 抽象出待执行的操作以参数化某对象,Command模式就像一个回调函数的对象实现。
  • 在不同的时刻指定、排列和执行请求,Commad有一个与初始请求无关的生存期。
  • 可以支持取消操作,在Command对象执行execute方法的之前把信息保存,提供一个unExecute方法恢复在执行前。也可以使用一个专门的Command来保存所有执行了的Commond对象比如UndoCommand来达到回滚操作。
  • 支持事物(Transaction),对一系列数据进行提交操作。