我有以下类:
<?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差不多,但不是将主题传递给观察者,而是传递一个事件(最终可以包含数据)。
我的观察者将监听一个"save"事件,事件链接到一个文件路径,并将字符串" file saved"存储在这个路径上。
接受一个"接口"参数,检查它的具体类型,然后把它看作是它的具体类型,这是一个不好的做法吗?
如果是,您有什么解决方案?
PS:我对我为这个主题设置的标题和标签不满意,如果你有更好的请帮助我:)
我在这里看到的唯一问题是您期望该接口的几个特定实现之一。如果您正在优化,有时这是可以的,但我通常希望看到声明的类名,例如:
if ($event instanceof MyConcreteEvent) {
// ...
}
如果您正在实现一个事件调度程序,那么您将向侦听特定$event->getName()
的Observer
订阅类。
查看http://symfony.com/doc/current/components/event_dispatcher/index.html获取事件信息。
我知道Observer和Event Dispatcher是不同的模式,但本质上它们是一样的
这是一个很好的实践,因为您可能有另一个类(实现相同的接口)具有类似/确切的行为,但使用不同的算法,并且可以很容易地解耦。
这是一个策略设计模式(查看更多模式在这里: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
}
}
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
}
}
在您的示例中,update方法变得越来越大,并且做得太多。它变得难以阅读。
最好的选择是将每个事件类型实现为观察者类中的方法,如: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
}
}
希望能有所帮助。