我有以下课程:
<?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:我对我为这个主题设置的标题和标签不满意,如果你有更好的请帮助我:)
答案 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
}
}
希望它有所帮助。