我使用 C++ 和 MFC 创建了一个类,它可以更轻松地向 CWnd
对象添加拖放功能。真的没有什么特别的。目前它是这样使用的:
- 创建CDropListener对象
- 在 CDropListener 对象上调用一个方法,说明您希望它对哪个文件扩展名使用react,以及一个函数指针,指示在删除文件时调用什么
- 用
CWnd
对象注册 - 在窗口被销毁时删除CDropListener对象
- 如果您想为不同的
CWnd
使用不同的文件扩展名,请重复上述所有步骤
必须为每个监听器创建一个类成员变量有点麻烦,我只是想知道哪种设计模式更适合这个。我只需要成员对象,这样我就可以在最后删除
它们。我想我可以只使用一个数组来存储它们,它会稍微简化它,但我也认为可能有更好的方法可以调用类似于 DropListener::RegisterListener(CWnd* wnd, CString& extension, void(*callback) callback)
它会为你处理所有的创建/注册/删除。
最佳答案
我不熟悉 MFC,但从面向对象的角度来看,您的设计可以改进。
首先确定您的需求的哪些方面最有可能发生变化,然后确定隔离这些变化所需的接口(interface)是:
变化:
- 您想听的东西(事件)
- 您想采取的行动(回调)
接口(interface):
- 事件通知器添加事件相关回调的机制
- 从通知者调用回调的机制
所以你需要一个 Event
界面,一个Callback
接口(interface),和一个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
)。这可能会返回一个值(如果您想要成功验证)或抛出特定的异常类型(确保记录契约(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/