事件监听器的最佳设计模式

时间:2014-06-17 09:13:55

标签: c++ design-patterns mfc

使用C ++& MFC我创建了一个类,可以更轻松地向CWnd对象添加拖放功能。真的没什么特别的。目前使用它是这样的:

  1. 创建CDropListener对象
  2. 在CDropListener对象上调用一个方法,说明您希望它对哪个文件扩展名作出反应,以及在删除文件时调用的函数指针
  3. 使用CWnd对象
  4. 注册
  5. 销毁窗口时删除CDropListener对象
  6. 如果您需要针对其他CWnd
  7. 的不同文件扩展名,请重复上述所有步骤

    为每个监听器创建一个类成员变量有点麻烦,我只是想知道哪个设计模式更适合这个。我只需要成员对象,这样我最后可以delete。我以为我可以使用一个数组来存储它们,它会简化它,但我也认为可能有一个更好的方法,你可以调用一个类似于DropListener::RegisterListener(CWnd* wnd, CString& extension, void(*callback) callback)的静态函数,它处理所有的为您创建/注册/删除。

1 个答案:

答案 0 :(得分:2)

我不熟悉MFC,但从OO的角度来看,您的设计可以改进。

首先确定您的需求最有可能发生变化的方面,然后确定隔离这些变更所需的接口:

<强>的变化:

  • 你想听的东西(活动)
  • 您要采取的行动(回调)

<强>接口

  • 将与事件相关的回调添加到事件通知程序的机制
  • 从通知程序调用回调的机制

所以你需要一个Event接口,一个Callback接口和一个Notifier接口。

在C ++中有一个名为std::function<T>的简单方法,其中T是任何可调用类型(指向函数的指针,functorlambda)。因此,您应该使用它来封装回调,以便为您的用户提供更多自由。

那么您想如何支持事件类型?这将告诉您是否需要支持不同的Event对象以及注册的外观:

// For example if you support just `Drop` events:
void addDropListener(std::function<T> callback);

// If you support many events:
void addListener(Event::Type evType, std::function<T> callback);

一旦你回答了你需要决定什么&#34;回调&#34;看起来像(上面例子中的T)。这可以返回一个值(如果您想要成功验证)或抛出特定的异常类型(确保记录合同)。然后问你是否想要一个被解雇的事件的副本(通常你会)。假设您很乐意只通过异常通知错误,那么您可以像这样输入预期的std :: function:

typedef std::function<void (const Event&)> EventCallback;

我建议您的Notifier实施者使用std::vector<EventCallback>std::map<Event::Type, std:vector<EventCallback>。如果您只想支持一种事件类型或为所有事件调用所有侦听器,则第一种方法很有用。当你只想通知听众某些类型的事件时,第二个是很方便的。

在任何情况下,如果您发现需要更改类代码以适应行为的微小更改,那么您需要进行一些重构。

希望有所帮助。 :)