我经常遇到以这种方式解决似乎合理的问题 - 我将给出一个具体的虚构示例,但我想知道名称,最佳做法 - 以及是否模式通常是一个好主意。
我需要通知订阅用户任意事件。让我们说其中一个过程评估"命令"并且用户订阅该事件但仅订阅一种订单。
我想代码应该看起来像这样:
<?php
// ...
public function processOrders() {
// ...
(new notifications\orders())->send( $typeOfOrderThatWasJustProcessed );
// ...
}
所以我创建了基本通知类:
<?php
abstract class notifications {
abstract public function configurationForm();
abstract public function send();
}
和这个特定用例的子类(语法无效,抽象方法签名与基类不同,请耐心等待):
namespace notifications;
class orders extends \notifications {
public function configurationForm() {
// prepare and return a form that will be rendered to HTML
// where the user chooses type of order that he is interested in
}
abstract public function send($type) {
// fetches needed users using the configuration which
// was provided via the form above
}
}
因此,每种类型的通知都必须包含任意参数。它们通知通知对象有关已处理的实体 - 以便通知代码可以决定自己将电子邮件发送给谁。
将此示例中的$type
视为动态值 - 可以通过数据库添加任意数量的类型。
如前所述,PHP中的abstract
类甚至无法实现这一点,我应该采用哪种方式?
答案 0 :(得分:1)
我会通过具体通知类的构造函数添加所需的参数,然后send不需要接收任何....有点像观察者场景中的命令对象......
当然这取决于参数的实际值是否在实例化时已知...如果不是,可能会将某种参数对象传递给构造函数,这样当参数更改时,参数对象会更新(因为它是PHP 5中的参考)?
namespace notifications;
class orders extends \notifications {
protected $type;
public function __construct($type) {
$this->type = $type;
}
public function configurationForm() {
//...
}
abstract public function send() {
// do stuff with $this->type
}
}
OR
namespace notifications;
class orders extends \notifications {
protected $parameters;
public function __construct(NotificationParameters $parameters) {
//$parameters might be a subclass of NotificationParameters, like OrderNotificationParameters
$this->parameters = $parameters;
}
public function configurationForm() {
//...
}
abstract public function send() {
// do stuff with $this->parameters->getType(); the value of which might have changed since construction time
}
}
你觉得怎么样?
更新 - 使用子类 命令模式我相信 - http://www.sitepoint.com/understanding-the-command-design-pattern/
namespace notifications;
abstract class orders extends \notifications {
abstract public function send() {
// do stuff with $this->type
}
}
class TypeAOrders extends orders {
public function send() {
// do Type A stuff
}
}
class TypeBOrders extends orders {
public function send() {
// do Type B stuff
}
}
...
public function processOrders() {
// ...
$commandBuilder->getNotification(typeOfOrderThatWasJustProcessed)->send();
//$commandBuilder knows which object to build depending on the type and pass any relevant parameters into the constructor...
// ...
}