将接口参数视为具体参数是不好的做法?

时间:2015-10-14 15:43:52

标签: php design-patterns

我有以下课程:

<?php

class SaveEvent implements EventInterface
{
    private $_path;

    public function __construct($path) { $this->_path = $path; }
    public function getName() { return 'save'; }
    public function getPath() { return $this->_path; }
}

class Observer implements ObserverInterface
{
    public function update(EventInterface $event)
    {
        switch ($event->getName()) {
            case 'save':
                $path = $event->getPath();
                file_put_contents($path, 'File saved');
                break;
            case 'quit':
                // Other event
        }
    }
}

正如您所看到的,我的“update”方法接受一个EventInterface参数,并根据事件的类型将触发一个特定的进程。它与SplSubject / SplObserver的实现大致相同,但不是将我的主题传递给我的观察者,而是传递一个事件(最终可以包含数据)。

我的观察者将侦听“保存”事件,链接到文件路径的事件,并将在此路径中存储字符串“File saved”。

接受“interfaced”参数,检查其具体类型并将其视为具体类型后,这是一种不好的做法吗?

如果是,你建议哪个解决方案来解决这个问题?

PS:我对我为这个主题设置的标题和标签不满意,如果你有更好的请帮助我:)

3 个答案:

答案 0 :(得分:1)

我在这里看到的唯一问题是你期待接口的几个特定实现之一。有时候如果你正在优化那就没关系,但我通常希望看到声明的类名,例如:

if ($event instanceof MyConcreteEvent) {
    // ...
}

如果您正在实施事件调度程序,那么您可以订阅Observer的类,该类会监听特定的$event->getName()

然后观察者将遍历订阅者,并调用每个订阅者。如果没有订阅者收听该事件,则不会发生任何事情。

结帐http://symfony.com/doc/current/components/event_dispatcher/index.html了解有关活动的信息。

我知道观察者和事件调度员是独立的模式,但他们心里却是一样的。

答案 1 :(得分:0)

这是一个很好的做法,因为你可能有另一个类(实现相同的接口),它具有相似/精确的行为但具有不同的算法,并且可以很容易地解耦。

这是一种策略设计模式(请参阅此处的更多模式:http://www.phptherightway.com/pages/Design-Patterns.html#strategy

实施例

    class YYYScraper implements LinkScraper
    {
        public function getLinks() {
        //gets links from the site www.yyy.com specific for this because the site has a different structure from the class below
        } 
    }
    class XXXScraper implements LinkScraper
    {
        public function getLinks() {
        //gets links from the site www.xxx.com
        } 
    }

class ProcessService
{
    public function gatherLinks(LinkScraper $linkScraper)
    {
        $linkScraper->getLinks();
        //save them or smth
    }
}

答案 2 :(得分:0)

在您的示例中,更新方法趋于变得越来越大,并且做得太多。它变得难以阅读。

最好的选择是将每个事件类型实现为观察者类中的方法,如:

class Observer implements ObserverInterface
{
    public function save(SaveEvent $event)
    {
        $path = $event->getPath();
        file_put_contents($path, 'File saved');
    }

    public function quit(QuitEvent $event)
    {
        // Other event
    }
}

希望它有所帮助。