【问题标题】:How to implement a full Observer pattern in PHP如何在 PHP 中实现完整的观察者模式
【发布时间】:2011-09-16 11:41:47
【问题描述】:

Observer Design Pattern 是松散耦合对象的解决方案,以便它们可以一起工作。在 PHP 中,您只需使用 two classes 即可轻松实现此功能。

基本上,您有一个能够通知和更新观察者列表其状态变化的主题。

我要解决的问题是知道如何处理警告观察者他们正在观看的对象的不同状态。

例如,假设我们有一个文件上传类,我们附加了一个日志记录类、websockets 类和一个图像调整大小类。正在观看的每个班级都想了解上传过程中的不同事件。

这个文件上传类可能有三个地方需要通知监听的类发生了什么事。

  • 上传错误(警报日志记录类)
  • 上传成功(提醒 websockets 类)
  • 上传成功,是图片文件(提醒图片调整大小类)

这是一个非常基本的示例,但是您如何处理不同观察者可能需要了解的多个事件?单独调用 notifyObservers() 是不够的,因为每个观察者都需要知道它收到的通知是什么。

一个想法是我可以通过调用说明正在观察什么类型的事件:

$this->notifyObservers('upload.error', this);

但是,这意味着我必须向观察者本身添加自定义切换,以了解如何处理不同的事件。

function observe($type, $object)
{
    if($type === 'upload.error') $this->dosomething();
    elseif($type === 'something.else') $this->otherthing();
    ...etc...
}

我发现这非常丑陋,因为它开始将观察者耦合回他们正在观察的类。

再一次,如果我只是通知观察者而不传递任何关于刚刚发生的事件的信息 - 他们必须自己猜测发生了什么,这意味着更多的 if() 检查。

【问题讨论】:

    标签: php observer-pattern


    【解决方案1】:

    观察者实际上并没有耦合到他们正在观察的类。观察者的处理程序和被观察对象之间的连接是使用文字字符串值(例如`upload.error')建立的,这意味着:

    1. 如果你想观察一个特定的对象,你必须事先知道它要发布的事件的名称;这是你不喜欢的“耦合”。
    2. 另一方面,如果您只对特定事件感兴趣,您可以观察该事件的任何类型的对象,而无需对该对象有任何了解。

    上面第 2 项是您关心的好处,但第 1 项该怎么办?

    如果您考虑一下,如果它们代表正在发生的不同事件,则需要某种方法来区分对同一观察者的回调。这些“标识符”,无论采取何种形式,都需要打包到被观察对象中,或者成为观察者库代码的一部分。

    在第一个实例中(在被观察对象内),您可能需要一种方法让观察者查询“您是否发布过事件 X?”在开始观察该事件的目标之前。目标可以很好地回答这个问题。这留下了耦合的苦涩味道,但是如果您希望任何对象观察任何其他对象,并且您事先不知道要观察 什么,我认为您不能做得更好。

    在第二种方法中,您将在您的库中定义许多众所周知的事件(作为类中的const?)。大概可以制作这样一个事件列表,因为该库处理一个具体的应用程序域,并且该域为事件提供了明显的选择。然后,库内部的类(最终会被观察到)和库外部的类(插入框架的观察者)都将使用这些标识符来区分事件。许多基于回调的 API(例如 Win32)使用的方法实际上与此相同。

    【讨论】:

    • 我刚刚找到了 Symfony Event Dispatcher 库,我想他们就像你说的那样处理了它。
    猜你喜欢
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多