【问题标题】:Design pattern where child classes have mandatory methods with arbitrary parameters子类具有带有任意参数的强制方法的设计模式
【发布时间】:2014-09-16 02:22:22
【问题描述】:

我经常遇到似乎可以通过这种方式解决的问题 - 我将给出一个具体的虚构示例,但 我想知道名称、最佳实践 - 以及这种模式是否好用总体思路

问题

我需要将任意事件通知订阅用户。假设其中一个流程评估“订单”并且用户订阅该事件但只订阅一种类型的订单

溶液的使用

我想代码应该是这样的:

<?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 类甚至是不可能的,我应该怎么看?

【问题讨论】:

    标签: php inheritance design-patterns abstract-class


    【解决方案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
        }
    }
    

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

    【讨论】:

    • 这是一个很好的解决方案,我只是讨厌我们在 php 5.3 上,所以 ` (new notifications\orders())->send( $type );` 变成了两行,但是这是一个小问题。我仍在等待对模式本身的洞察——它的名称和更多关于它的信息,然后再投下已回答的复选框。
    • 是的,php 5.4 在语法上要好很多...我相信它是一种命令设计模式 (sitepoint.com/understanding-the-command-design-pattern).. 问题,configurationForm 如何在这里发挥作用?因为如果我们有像(new notifications\orders())-&gt;send( $type )(或(new notifications\orders($type))-&gt;send())这样的行,则该对象被创建,使用然后立即销毁,所以该方法对我来说似乎没有用过。另外,也许可以将类型的逻辑从完全发送方法,并且每种类型都有不同的通知\订单子类?
    • 我决定采用的明显、清晰和巧妙的解决方案是__construct($type) FYI :) 谢谢!
    • 没有问题!我喜欢你的 kint 工具 raveren.github.io/kint
    猜你喜欢
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 2016-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多