设计模式,其中子类具有包含任意参数的强制方法

时间:2014-07-24 13:34:11

标签: php inheritance design-patterns abstract-class

我经常遇到以这种方式解决似乎合理的问题 - 我将给出一个具体的虚构示例,但我想知道名称,最佳做法 - 以及是否模式通常是一个好主意

问题

我需要通知订阅用户任意事件。让我们说其中一个过程评估"命令"并且用户订阅该事件但仅订阅一种订单。

解决方案的用法

我想代码应该看起来像这样:

<?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类甚至无法实现这一点,我应该采用哪种方式?

1 个答案:

答案 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...
    // ...
}