kir*_*kun 22 c++ iterator design-patterns callback inversion-of-control
假设我有一个[acme]对象流,我想通过API公开.我有两个选择,回调和迭代器.
// API #1
// This function takes a user-defined callback
// and invokes it for each object in the stream.
template<typename CallbackFunctor>
void ProcessAcmeStream(CallbackFunctor &callback);
Run Code Online (Sandbox Code Playgroud)
// API #2
// Provides the iterator class AcmeStreamIterator.
AcmeStreamIterator my_stream_begin = AcmeStreamIterator::begin();
AcmeStreamIterator my_stream_end = AcmeStreamIterator::end();
Run Code Online (Sandbox Code Playgroud)
API#1从用户手中获取程序的控制流,并且在整个流被消耗之前不会返回(暂时忘记异常).
API#2保留用户手中的控制流,允许用户自己前进流.
API#1感觉更高级别,允许用户立即跳转到业务逻辑(回调函子).另一方面,API#2感觉更灵活,允许用户更低级别的控制.
从设计的角度来看,我应该选择哪一个?我还没有看到更多的利弊吗?未来有哪些支持/维护问题?
迭代器方法更灵活,回调版本可以通过现有算法轻松实现第一个版本:
std::for_each( MyStream::begin(), MyStream::end(), callback );
Run Code Online (Sandbox Code Playgroud)
IMO,第二个显然是优越的.虽然我可以(有点)理解你的感觉它是较低的水平,但我认为这是不正确的.第一个定义了它自己的"更高级别"的特定概念 - 但它与C++标准库的其余部分不相符,并且最终使用起来相对困难.特别是,它要求如果用户想要与标准算法等效的东西,则必须从头开始重新实现,而不是使用现有代码.
第二个完全适合库的其余部分(假设您正确实现了迭代器),并为用户提供了通过标准算法(和/或遵循以下新的非标准算法)在更高级别处理数据的机会.标准模式).
回调函数优于迭代器的一个优点是API的用户不会陷入迭代.可以很容易地比较错误的迭代器,或使用错误的比较操作或以其他方式失败.回调API可以防止这种情况发生.
使用回调很容易取消枚举,BTW:只要让回调返回bool并继续,只要它返回true.