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

标签 c++ design-patterns mfc

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

  1. 创建CDropListener对象
  2. 在 CDropListener 对象上调用一个方法,说明您希望它对哪个文件扩展名使用react,以及一个函数指针,指示在删除文件时调用什么
  3. CWnd 对象注册
  4. 在窗口被销毁时删除CDropListener对象
  5. 如果您想为不同的 CWnd
  6. 使用不同的文件扩展名,请重复上述所有步骤

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

最佳答案

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

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

变化:

  • 您想听的东西(事件)
  • 您想采取的行动(回调)

接口(interface):

  • 事件通知器添加事件相关回调的机制
  • 从通知者调用回调的机制

所以你需要一个 Event界面,一个Callback接口(interface),和一个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);

一旦您回答了您需要决定“回调”是什么样的(在上面的示例中为 T)。这可能会返回一个值(如果您想要成功验证)或抛出特定的异常类型(确保记录契约(Contract))。然后询问您是否想要已触发事件的拷贝(通常您会)。假设您很高兴只通过异常收到错误通知,那么您可以像这样对预期的 std::function 进行类型定义:

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

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

无论如何,如果您发现需要更改类代码以适应行为的微小变化,那么您需要进行一些重构。

希望对您有所帮助。 :)

关于c++ - 事件监听器的最佳设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24259873/

相关文章:

python - 最小工作示例 tensorflow 服务客户端

c++ - 按值返回 boost ublas 矩阵仅在 vs2012 的发布配置中工作

c++ - 避免公共(public)类中重复代码

java - 使用不相关类的相关类的有效设计

c++ - 在 MFC 上选择多个 UINT 格式时出现语法错误

c++ - 从内存地址偏移

c++ - 播放视频时在 qwidget 上绘图

javascript - 使用回调异步加载 JavaScript 文件

c++ - 使用 C++ MFC,获取添加到浏览器(Chrome、IE 或 Firefox)的扩展列表

visual-c++ - 如何在 MFC 对话框中添加关闭按钮