事件侦听器的最佳设计模式
Best design pattern for event listeners
使用c++ &MFC我已经创建了一个类,使它更容易添加拖放功能的CWnd
对象。这真的没什么特别的。当前的用法如下:
- 创建cdropllistener对象
- 在CDropListener对象上调用一个方法,说明您希望它对哪个文件扩展名做出反应,并提供一个函数指针,说明当文件被删除时要调用什么
- 注册
CWnd
对象 - 当窗口被销毁时删除CDropListener对象
- 如果您想要不同的
CWnd
文件扩展名,请重复上述所有步骤
为每个侦听器创建类成员变量有点麻烦,我只是想知道哪种设计模式更适合于此。我只需要成员对象,这样我就可以在最后对它们进行delete
。我想我可以用一个数组来存储它们,它会简化一点,但我也认为可能有一个更好的方法,你可以调用一个类似于DropListener::RegisterListener(CWnd* wnd, CString& extension, void(*callback) callback)
的静态函数,它为你处理所有的创建/注册/删除
我不熟悉MFC,但从面向对象的角度来看,您的设计可以改进。
首先确定需求的哪些方面最有可能更改,然后确定隔离这些更改所需的接口是什么:
变化:
- 您想要监听的内容(事件)
- 你想要采取的动作(回调)
接口:
- 向事件通知器中添加与事件相关的回调的机制
- 从通知器调用回调的机制
所以你需要一个Event
接口,一个Callback
接口和一个Notifier
接口。
在c++中有一个方便的东西叫做std::function<T>
,其中T
是任何可调用类型(指向函数的指针,functor
, lambda
)。所以你应该用它来封装你的回调,给你的用户更多的自由。
你想支持多少种事件类型?这将告诉您是否需要支持不同的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
在上面的例子)。这可以返回一个值(如果您想要成功验证)或抛出一个特定的异常类型(确保记录契约)。然后询问是否需要已触发事件的副本(通常需要)。假设您很高兴只通过异常收到错误通知,那么您可以像这样定义std::函数:
typedef std::function<void (const Event&)> EventCallback;
我建议你的Notifier
实现者使用std::vector<EventCallback>
或std::map<Event::Type, std:vector<EventCallback>
。如果您希望只支持一种事件类型或为所有事件调用所有侦听器,那么第一个方法很有用。当您只想通知侦听器特定类型的事件时,第二个选项很方便。
在任何情况下,如果你发现你需要改变你的类代码来适应行为的微小变化,那么你需要一些重构。
希望有帮助。:)
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 资源管理设计模式
- 用于在回调中调用解析器的设计模式
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 在这种情况下我应该使用哪种设计模式
- C++中物体改变识别的设计模式?
- 确保所有构造函数调用相同的函数 c++ 设计模式
- 需要实例化不同类/对象并在启动时确定的硬件插槽的设计模式
- 设计模式,以避免不必要地添加抽象函数以适应新功能
- 工厂设计模式优化
- 使用C++模板的数据映射器设计模式
- 为什么以及如何使用原型设计模式
- 具有多个继承共享一个资源的对象 - 寻找良好的设计模式
- 在C++中创建观察器设计模式的好方法
- 现代C++在多大程度上消除了对设计模式的需求?
- 对于存储另一个类所需信息的类,例如其构造,是否有设计模式?
- 用于在硬件接口之间切换的最佳设计模式
- 实时应用中图像采集和图像处理的设计模式或最佳实践
- 使用通用方法的最佳实践/设计模式
- 事件侦听器的最佳设计模式