命令模式

意图:将一个命令请求封装成一个对象。解决命令的请求者和命令的实现者之间的耦合关系。

经典的命令模式包括4个角色:

  • Command:定义命令的统一接口
  • ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
  • Receiver:命令的实际执行者
  • Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。

下面对上面四个角色的经典实现用代码来进行说明,这也是大部分文章对命令模式的运用方式。

经典代码实现:

 

1 /// <summary>

2 /// Command角色

3 /// </summary>

4 public interface ICommand

5 {

6 void Execute();

7 }

8

9 /// <summary>

10 /// ConcreteCommand角色A

11 /// </summary>

12 public class ConcreteCommandA : ICommand

13 {

14 private Receiver receiver = null;

15

16 public ConcreteCommandA(Receiver receiver)

17 {

18 this.receiver = receiver;

19 }

20

21 public void Execute()

22 {

23 this.receiver.DoA();

24 }

25 }

26

27 /// <summary>

28 /// ConcreteCommand角色B

29 /// </summary>

30 public class ConcreteCommandB : ICommand

31 {

32 private Receiver receiver = null;

33

34 public ConcreteCommandB(Receiver receiver)

35 {

36 this.receiver = receiver;

37 }

38

39 public void Execute()

40 {

41 this.receiver.DoB();

42 }

43 }

44

45 /// <summary>

46 /// Receiver角色

47 /// </summary>

48 public class Receiver

49 {

50 public void DoA()

51 {

52 //DoSomething

53 }

54

55 public void DoB()

56 {

57 //DoSomething

58 }

59 }

60

61 /// <summary>

62 /// Invoker角色

63 /// </summary>

64 public class Invoker

65 {

66 private ICommand command = null;

67

68 //设置命令

69 public void SetCommand(ICommand command)

70 {

71 this.command = command;

72 }

73 //执行命令

74 public void RunCommand()

75 {

76 command.Execute();

77 }

78 }

79

80 /// <summary>

81 /// 客户端调用

82 /// </summary>

83 public class Client

84 {

85 public Client()

86 {

87 Receiver receiver = new Receiver();

88 Invoker invoker = new Invoker();

89 invoker.SetCommand(new ConcreteCommandA(receiver));

90 invoker.RunCommand();

91 invoker.SetCommand(new ConcreteCommandB(receiver));

92 invoker.RunCommand();

93 }

94 }

 

模式总结

  5.1 优点

    5.1.1 解除了请求者与实现者之间的耦合,降低了系统的耦合度。

    5.1.2 对请求排队或记录请求日志,支持撤销操作。

    5.1.3 可以容易地设计一个组合命令。

    5.1.4 新命令可以容易地加入到系统中。

  5.2 缺点

    5.2.1 因为针对每一个命令都需要设计一个具体命令类,使用命令模式可能会导致系统有过多的具体命令类。

  5.3 适用场景

    5.3.1 当需要对行为进行"记录、撤销/重做"等处理时。

    5.3.2 系统需要将请求者和接收者解耦,使得调用者和接收者不直接交互。

    5.3.3 系统需要在不同时间指定请求、请求排队和执行请求。

    5.3.4 系统需要将一组操作组合在一起,即支持宏命令。

使用场景:

任务队列:Invoker将命令放入队列里,Receiver从队列里拿出命令来执行。也就是说,命令本身的执行逻辑是Invoker定义的。

日志记录:如我们拿到命令后可以序列化到硬盘,然后根据检查点在系统宕机恢复后重新执行命令。

posted on 2017-08-11 15:48  张小贱1987  阅读(182)  评论(0编辑  收藏  举报

导航