Skip to content

命令模式 / Command

代码示例

js
// 命令接口
class Command {
  execute() {
    throw new Error("必须实现 'execute'方法");
  }
}

// 接收者对象
class Receiver {
  performAction() {
    // 执行具体的操作逻辑
    console.log('执行操作');
  }
}

// 具体的命令对象
class ConcreteCommand extends Command {
  constructor(receiver) {
    super();
    this.receiver = receiver;
  }

  execute() {
    this.receiver.performAction();
  }
}

// 调用者(Invoker)对象
class Invoker {
  setCommand(command) {
    this.command = command;
  }

  executeCommand() {
    this.command.execute();
  }
}

// 使用示例
const receiver = new Receiver();
const command = new ConcreteCommand(receiver);
const invoker = new Invoker();

invoker.setCommand(command);
invoker.executeCommand(); // 输出:执行操作

React 函数式组件代码示例

ts
// 定义接收者类型
interface Receiver {
  submitForm(data: any): void;
}

// 接收者对象
class FormSubmitter implements Receiver {
  submitForm(data: any): void {
    console.log('提交表单数据:', data);
    // 这里可以包含提交表单到服务器的逻辑
  }
}

// 命令类型(在函数式编程中,命令通常就是函数)
type Command = (data: any) => void;

// 创建命令函数
function createFormSubmitCommand(submitter: Receiver): Command {
  return (data: any) => submitter.submitForm(data);
}

// React 函数式组件
const MyForm: React.FC = () => {
  // 创建接收者对象
  const formSubmitter = new FormSubmitter();

  // 创建命令
  const formSubmitCommand: Command = createFormSubmitCommand(formSubmitter);

  // 获取表单数据
  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    const formData = {
      /* ... */
    }; // 假设这里是从表单中获取的数据

    // 执行命令
    formSubmitCommand(formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* 表单输入字段 */}
      <button type="submit">提交</button>
    </form>
  );
};

组合多个命令

命令模式允许我们将多个命令组合成一个宏命令。我们可以创建多个命令对象,然后将它们组合起来,形成一个宏命令来执行。

ts
// 命令接口
interface Command {
  execute(): void;
}

// 具体命令类
class OpenFileCommand implements Command {
  execute(): void {
    console.log('打开文件');
  }
}

class SaveFileCommand implements Command {
  execute(): void {
    console.log('保存文件');
  }
}

class CloseFileCommand implements Command {
  execute(): void {
    console.log('关闭文件');
  }
}

// 宏命令类
class MacroCommand implements Command {
  private commands: Command[] = [];

  add(command: Command): void {
    this.commands.push(command);
  }

  execute(): void {
    this.commands.forEach((command) => command.execute());
  }
}

// 使用示例
const macroCommand = new MacroCommand();
macroCommand.add(new OpenFileCommand());
macroCommand.add(new SaveFileCommand());
macroCommand.add(new CloseFileCommand());

// 执行宏命令
macroCommand.execute();

TIP

上面这段代码实际上还用到了组合模式,在组合模式中,组合对象和单个对象都遵循相同的接口,这是组合模式的关键特征。在上述代码中,MacroCommand 和具体的命令类(如 OpenFileCommand)都实现了相同的 Command 接口。这样,无论是单个命令还是宏命令,都可以通过调用 execute 方法来执行。

组合模式的好处在于,它允许我们构建复杂的命令结构,同时保持代码的简洁和可维护性。我们可以创建包含其他宏命令的宏命令,或者将单个命令和宏命令混合在一起,从而实现非常灵活的命令组合。