控制反转的利弊

kir*_*kun 22 c++ iterator design-patterns callback inversion-of-control

假设我有一个[acme]对象流,我想通过API公开.我有两个选择,回调和迭代器.

API#1:回调

// 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:迭代器

// 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感觉更灵活,允许用户更低级别的控制.

从设计的角度来看,我应该选择哪一个?我还没有看到更多的利弊吗?未来有哪些支持/维护问题?

Dav*_*eas 9

迭代器方法更灵活,回调版本可以通过现有算法轻松实现第一个版本:

std::for_each( MyStream::begin(), MyStream::end(), callback );
Run Code Online (Sandbox Code Playgroud)


Jer*_*fin 6

IMO,第二个显然是优越的.虽然我可以(有点)理解你的感觉它是较低的水平,但我认为这是不正确的.第一个定义了它自己的"更高级别"的特定概念 - 但它与C++标准库的其余部分不相符,并且最终使用起来相对困难.特别是,它要求如果用户想要与标准算法等效的东西,则必须从头开始重新实现,而不是使用现有代码.

第二个完全适合库的其余部分(假设您正确实现了迭代器),并为用户提供了通过标准算法(和/或遵循以下新的非标准算法)在更高级别处理数据的机会.标准模式).


sbi*_*sbi 5

回调函数优于迭代器的一个优点是API的用户不会陷入迭代.可以很容易地比较错误的迭代器,或使用错误的比较操作或以其他方式失败.回调API可以防止这种情况发生.

使用回调很容易取消枚举,BTW:只要让回调返回bool并继续,只要它返回true.

  • 我在维护期间遇到过这种问题.我需要优先处理项目的处理顺序.而不是仅仅改变类以便每个人都免费获得更改,我必须找到使用它的所有代码,并改变它. (2认同)
  • 国际海事组织,这里的推理是有缺陷的.如果您假设C++程序员不知道如何使用迭代器,您可能还需要假设他不知道如何编写函数或函子来用作回调函数.相反,如果他知道C++,那么他*会知道迭代器. (2认同)