You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在处理不同参数时使用命令模式(Command Pattern)

命令模式中带运行时参数的命令对象处理问题

查看命令模式的UML图可知,调用者对象(调用命令对象execute()方法的类)必须提供setCommand()方法,让客户端代码为其设置合适的命令对象。但当命令对象拥有仅在运行时才确定的不同参数时,该方法该如何使用?下面举例说明:

class Messenger
{
  public function sendEmail(string $email, string $subject, string $body): void { ... }
  public function sendSms(string $phone, string $text): void { ... }
}

interface Command
{
  public function execute(): void;
}

class SendEmailCommand implements Command
{
  private readonly Messenger $messenger;
  private readonly string $email;
  private readonly string $subject;
  private readonly string $body;

  public function __construct(Messenger $messenger)
  {
    $this->messenger = $messenger;
  }

  public function setEmail(string $email): void { $this->email = $email; }
  public function setSubject(string $subject): void { $this->subject = $subject; }
  public function setBody(string $body): void { $this->body = $body; }

  public function execute(): void
  {
    $this->messenger->sendEmail($this->email, $this->subject, $this->body);
  }
}

class SendSmsCommand implements Command
{
  private readonly Messenger $messenger;
  private readonly string $phone;
  private readonly string $text;

  public function __construct(Messenger $messenger)
  {
    $this->messenger = $messenger;
  }

  public function setPhone(string $phone): void { $this->phone = $phone; }
  public function setText(string $text): void { $this->text = $text; }

  public function execute(): void
  {
    $this->messenger->sendSms($this->phone, $this->text);
  }
}

在这种场景下,调用者类中的setCommand(Command $command)方法还有多大用处?在部分语言中,调用setX()方法甚至会报错,因为Command接口并未定义这些方法。像下面这样实现是否是个坏主意?

class EmailSendButton
{
  private readonly Messenger $messenger;

  public function __construct(Messenger $messenger)
  {
    $this->messenger = $messenger;
  }

  public function onClick(): void
  {
    $email = $this->getEmail();
    $subject = $this->getSubject();
    $body = $this->getBody();

    $sendEmailCommand = new SendEmailCommand($this->messenger);
    $sendEmailCommand->setEmail($email);
    $sendEmailCommand->setSubject($subject);
    $sendEmailCommand->setBody($body);
    $sendEmailCommand->execute();
  }
}

我知道在类内部实例化另一个类并不理想,会产生耦合,但该如何解决这个问题?我曾考虑用setCommand(SendEmailCommand $sendEmailCommand)替代更通用的setCommand(Command $command),但在我看来这给客户端代码带来的复杂度远大于收益。


内容的提问来源于stack exchange,提问作者zer0uno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 02:45:15