如何在处理不同参数时使用命令模式(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
相关产品推荐
相关产品推荐

