【发布时间】:2014-05-26 20:08:41
【问题描述】:
在我的应用程序的许多情况下,我需要 A 类将自己注册为 B 类的侦听器,以便在发生某些事情时接收通知。在每种情况下,我都定义了一个单独的接口 B 实现并且 A 可以调用 do。因此,例如,A 将具有以下方法:
void registerSomeEventListener(SomeEventListener l);
另外,在很多情况下,B 需要支持多个监听器,所以我重新实现了注册和 notifyAll 逻辑。
我知道的一种通用方法是拥有一些 EventListener(由 A 实现)和 EventNotifier(由 B 实现)类。在这种情况下,每个事件都由一个字符串标识,并且 A 实现了该方法:
void eventNotified(string eventType);
我认为这不是一个好的解决方案。如果 A 侦听多个事件,则会导致许多 if-else 语句,并且当事件名称仅在侦听器或通知器中更改时可能会导致错误。
我想知道在 C++ 中实现观察者模式的正确方法是什么?
【问题讨论】:
-
我wrote something about this 不久前。我的“听众”只是可调用的实体。我不确定它是否完全适合您的用例,但它可能值得一看。
-
没有对错之分。由于各种原因,有几十种方法被实施。最常见的是使用虚函数,并让侦听器从这个基本接口派生。但它有局限性。您还可以存储单独的类实例和方法名称,以便只有那些注册的类接收回调。如果您使用 boost 那么他们有一些很好的实用程序来处理这个问题。如果您更愿意自己编写,那么您需要研究模板,以及谁来定义指向类方法的指针..
-
@Dan 所以你的意思是最常见的方式是非泛型方式?只需为每个场景创建一个特定的侦听器类型,然后从它派生类 A 并实现其功能?
-
我不会这么说,但是你得到的越通用,它的性能就越差。您不能拥有指向类实例的通用指针。除非它们都从同一个基类派生,否则该类的方法指针必须在基类中定义。但是,如果您不关心性能,那么您可以从具有虚拟 Invoke 的基类创建一个 thunking 层,该虚拟 Invoke 代理特定类和方法函数绑定。但是虚拟调用通常会导致缓存未命中。你通常可以忍受。
-
如果你需要更高性能的东西,IE:每帧被调用数百次,那么你应该使用更具体的回调机制..
标签: c++ oop design-patterns observer-pattern