命令模式(Command Pattern)学习笔记

命令模式(Command Pattern)学习笔记

AssistedByChatGPT

命令模式(Command Pattern)属于行为设计模式,它将请求或简单操作封装为一个对象。这种模式允许用户发出请求的同时,不必了解请求的具体操作或请求的接收者是谁。命令模式通常用于实现请求的排队、记录请求日志以及实现可撤销操作等功能。常常和备忘录模式一起使用,用于实现撤销功能,之后学到这了会在这里贴上链接。

核心组件

命令模式主要涉及以下几个角色:

  1. 命令(Command):定义所有具体命令类的接口。通常会声明一个执行命令的方法。
  2. 具体命令(Concrete Command):实现命令接口,定义了对请求接收者的调用行为。
  3. 请求者/调用者(Invoker):负责调用命令对象执行请求。
  4. 接收者(Receiver):执行与请求相关的操作。具体命令对象对该类的方法进行调用,以实现具体的操作。
  5. 客户端(Client):创建具体命令对象,并设置其接收者。

优点

  • 解耦调用者和接收者:调用者和接收者之间没有直接联系,调用者只需要知道如何发送命令。
  • 扩展性强:新增命令或者更改命令的实现不会影响现有的调用者代码。
  • 支持撤销操作:可以通过实现一个撤销命令的方法来支持撤销操作。
  • 易于实现操作的记录和分享:命令对象可以被序列化并持久化,从而允许操作的记录、撤销、重放或分享。

示例

假设我们有一个简单的文本编辑器,需要实现文本的剪切、复制和粘贴功能。我们可以使用命令模式来实现这些功能。

首先,定义Command接口和Receiver

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 命令接口
public interface ICommand
{
    void Execute();
}

// 接收者
public class TextEditor
{
    public void Cut()
    {
        Console.WriteLine("Cutting text");
    }

    public void Copy()
    {
        Console.WriteLine("Copying text");
    }

    public void Paste()
    {
        Console.WriteLine("Pasting text");
    }
}

接下来,定义具体的命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 具体命令
public class CutCommand : ICommand
{
    private TextEditor _editor;

    public CutCommand(TextEditor editor)
    {
        _editor = editor;
    }

    public void Execute()
    {
        _editor.Cut();
    }
}

public class CopyCommand : ICommand
{
    private TextEditor _editor;

    public CopyCommand(TextEditor editor)
    {
        _editor = editor;
    }

    public void Execute()
    {
        _editor.Copy();
    }
}

public class PasteCommand : ICommand
{
    private TextEditor _editor;

    public PasteCommand(TextEditor editor)
    {
        _editor = editor;
    }

    public void Execute()
    {
        _editor.Paste();
    }
}

最后,实现Invoker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class CommandInvoker
{
    private ICommand _command;

    public void SetCommand(ICommand command)
    {
        _command = command;
    }

    public void ExecuteCommand()
    {
        _command.Execute();
    }
}

客户端代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Program
{
    static void Main(string[] args)
    {
        TextEditor editor = new TextEditor();
        CommandInvoker invoker = new CommandInvoker();

        invoker.SetCommand(new CutCommand(editor));
        invoker.ExecuteCommand();

        invoker.SetCommand(new CopyCommand(editor));
        invoker.ExecuteCommand();

        invoker.SetCommand(new PasteCommand(editor));
        invoker.ExecuteCommand();
    }
}

在这个例子中,TextEditor是接收者,实现了剪切、复制和粘贴的实际操作;CutCommandCopyCommandPasteCommand是具体的命令;CommandInvoker是调用者,通过命令对象间接操作接收者。客户端通过设置调用者的命令对象来执行具体的操作,实现了调用者和接收者之间的解耦。

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus