[关闭]
@BertLee 2017-08-19T10:17:57.000000Z 字数 3280 阅读 895

行为型之命令模式

序言

  命令模式把发出命令的责任和执行命令的责任分隔开,分别委托给不同的对象。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。
  命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
  使用命令模式会导致系统增加过度的具体命令类,使得其实现不切合实际。

命令模式涉及到5个角色,分别是:

  • 命令角色:接口或者抽象类,抽象方法包含了命令的执行操作
  • 具体命令角色:类,实现命令的执行方法,调用接受者的相应操作
  • 请求者角色:类,负责调用命令的执行请求,相关的方法,叫行动方法
  • 接受者角色:类,负责具体实施和执行1个请求,相关的方法,叫行动方法

  电视机会有开机,关机,换台的基本命令操作,我们不需要知道其内部实现,在这里我们是客户端,而电视机可以被看做命令接受者,遥控器则可以被看做是命令请求者,我们只需要和请求者打交道即可。

命令模式

  命令模式的结构如下图:



套路:
1. 将接受者要执行的命令拆分,分别创建对应的命令类,并把接受者对象委托到命令类中
2. 创建请求者类,添加所有命令的委托对象,对于各自的命令,要创建各自的行动方法

  1. /**
  2. * 命令接受者-电视机
  3. */
  4. public class TV {
  5. private int currentChannel = 0;
  6. //行动方法
  7. public void trunOn(){
  8. System.out.println("电视机开启");
  9. }
  10. //行动方法
  11. public void turnOff(){
  12. System.out.println("电视机关闭");
  13. }
  14. //行动方法
  15. public void change(int channel){
  16. this.currentChannel = channel;
  17. System.out.println("切换到频道" + currentChannel);
  18. }
  19. }
  1. /**
  2. * 命令接口
  3. */
  4. public interface Command {
  5. public void execute();
  6. }
  1. /**
  2. * 打开命令
  3. */
  4. public class OnCommand implements Command{
  5. private TV tv;
  6. public OnCommand(TV tv){
  7. this.tv = tv;
  8. }
  9. public void execute() {
  10. tv.trunOn();
  11. }
  12. }
  1. /**
  2. * 换台命令
  3. */
  4. public class ChangeCommand implements Command{
  5. private TV tv;
  6. private int channel;
  7. public ChangeCommand(TV tv,int channel){
  8. this.tv = tv;
  9. this.channel = channel;
  10. }
  11. public void execute() {
  12. tv.change(channel);
  13. }
  14. }
  1. /**
  2. * 关闭命令
  3. */
  4. public class OffCommand implements Command {
  5. private TV tv;
  6. public OffCommand(TV tv){
  7. this.tv = tv;
  8. }
  9. public void execute() {
  10. tv.turnOff();
  11. }
  12. }
  1. /**
  2. * 复合命令,由多个连续的基本命令操作组成
  3. */
  4. public class ManyCommand implements Command{
  5. //可设计为命令队列
  6. private List<Command> commands = new ArrayList<Command>();
  7. public void add(Command command){
  8. commands.add(command);
  9. }
  10. public void remove(Command command){
  11. commands.remove(command);
  12. }
  13. public void execute() {
  14. for(Command command :commands){
  15. command.execute();
  16. }
  17. }
  18. }
  1. /**
  2. * 命令请求者-遥控器
  3. */
  4. public class Control {
  5. private Command offCommand;
  6. private Command onCommand;
  7. private Command changeCommand;
  8. private Command manyCommand;
  9. //行动方法
  10. public void turnOn(){
  11. onCommand.execute();
  12. }
  13. //行动方法
  14. public void trunOff(){
  15. offCommand.execute();
  16. }
  17. //行动方法
  18. public void change(){
  19. changeCommand.execute();
  20. }
  21. //行动方法
  22. public void exeManyCommand(){
  23. manyCommand.execute();
  24. }
  25. public void setOffCommand(Command offCommand) {
  26. this.offCommand = offCommand;
  27. }
  28. public void setOnCommand(Command onCommand) {
  29. this.onCommand = onCommand;
  30. }
  31. public void setChangeCommand(Command changeCommand) {
  32. this.changeCommand = changeCommand;
  33. }
  34. public void setManyCommand(Command manyCommand) {
  35. this.manyCommand = manyCommand;
  36. }
  37. }
  1. /**
  2. * 测试命令模式
  3. */
  4. public class CommandTest {
  5. @Test
  6. public void testCommand(){
  7. //命令接受者
  8. TV tv = new TV();
  9. //命令,绑定接受者
  10. OnCommand onCommand = new OnCommand(tv);
  11. ChangeCommand changeCommand = new ChangeCommand(tv, 3);
  12. OffCommand offCommand = new OffCommand(tv);
  13. //命令请求者,绑定命令
  14. Control control = new Control();
  15. control.setOnCommand(onCommand);
  16. control.setChangeCommand(changeCommand);
  17. control.setOffCommand(offCommand);
  18. //触发
  19. control.turnOn();
  20. control.trunOff();
  21. control.change();
  22. //复合命令
  23. ManyCommand manyCommand = new ManyCommand();
  24. manyCommand.add(onCommand);
  25. manyCommand.add(changeCommand);
  26. manyCommand.add(offCommand);
  27. //命令请求者绑定复合命令
  28. control.setManyCommand(manyCommand);
  29. //触发
  30. control.exeManyCommand();
  31. }
  32. }

吹牛:
1. 命令模式将对象的请求操作和执行操作分割开来,实现解耦
2. 命令模式使新的命令很容易地被加入到系统里。
3. 能较容易地设计一个命令队列。
4. 可以容易地实现对请求的撤销和恢复。

应用场景:

  • 可使用命令模式作为回调。先将行动方法注册上,然后在需要时调用。
  • 需要在不同的时间制定请求、将请求排队。1个命令对象和原先的请求发出者可以有不同的生命周期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接受者可以是在本地,也可以在网络的另外一个地址,命令对象可以在序列化之后传送到另外一台机器上去。

后记

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注