许多重复的switch语句似乎需要DRY'd。有什么建议吗?(包括什么都不做!
AnimMapIter _iter;
_iter = _animations->find(name);
if(_iter == _animations->end()) return;
if(_curName != name) {
_curName = name;
switch(dir) {
case DIR_FORWARD_LOOPING: /* Fall through to DIR_FORWARD_NONLOOPING */
case DIR_FORWARD_NONLOOPING:
_iter->second->First();
break;
case DIR_REVERSE_LOOPING: /* Fall through to DIR_REVERSE_NONLOOPING */
case DIR_REVERSE_NONLOOPING:
_iter->second->Last();
break;
}
} else {
switch(dir) {
case DIR_FORWARD_LOOPING: /* Fall through to DIR_FORWARD_NONLOOPING */
case DIR_FORWARD_NONLOOPING:
_iter->second->Next();
break;
case DIR_REVERSE_LOOPING: /* Fall through to DIR_REVERSE_NONLOOPING */
case DIR_REVERSE_NONLOOPING:
_iter->second->Previous();
break;
}
switch(dir) {
case DIR_FORWARD_LOOPING:
if(_iter->second->IsAtEnd())
_iter->second->First();
break;
case DIR_FORWARD_NONLOOPING:
if(_iter->second->IsAtEnd())
_iter->second->Last();
break;
case DIR_REVERSE_LOOPING:
if(_iter->second->IsAtFront())
_iter->second->Last();
break;
case DIR_REVERSE_NONLOOPING:
if(_iter->second->IsAtFront())
_iter->second->First();
break;
}
}
else 下的所有内容都应该折叠成一个开关,以使相关步骤更近;例如
case DIR_FORWARD_LOOPING:
_iter->second->Next();
if (_iter->second->IsAtEnd()) {
_iter->second->First();
}
break;
。都在那一种情况下。 重复几个函数调用并不是什么大问题,因为它使整个操作顺序更加清晰。
按照
以下思路将逻辑推送到任何_iter->second
中(假设您已经展示的方法存在):
class WhateverItIs
{
public:
void Start() { if (m_forward) First(); else Last(); }
void Stop() { if (m_forward) Last(); else First(); }
void Advance()
{
if (m_forward)
Next();
else
Previous();
if (IsLast())
{
if (m_loop)
Start();
else
Stop();
}
}
private:
bool IsLast() const
{
return m_forward ? IsAtEnd() : IsAtFront();
}
// Direction and looping are independent concepts.
bool m_forward;
bool m_loop;
};
然后你可以写:
AnimMapIter _iter;
_iter = _animations->find(name);
if(_iter == _animations->end()) return;
if(_curName != name) {
_curName = name;
_iter->second->Start();
} else {
_iter->second->Advance();
}
编辑:使用自由函数并保留常量的示例。
void Start(Strip* s, bool forward)
{ if (forward) s->First(); else s->Last(); }
void Stop(Strip* s, bool forward)
{ if (forward) s->Last() else s->First(); }
void Advance(Strip* s, bool forward, bool loop)
{
if (forward)
s->Next();
else
s->Previous();
if (IsLast(s, forward))
{
if (loop)
Start(s);
else
Stop(s);
}
}
bool IsLast(const Strip* s, bool forward) const
{
return forward ? s->IsAtEnd() : s->IsAtFront();
}
bool Projector::IsForward() const
{
return dir == DIR_FORWARD_LOOPING || dir == DIR_FORWARD_NONLOOPING;
}
bool Projector::IsLooping() const
{
return dir == DIR_REVERSE_LOOPING || dir == DIR_FORWARD_LOOPING;
}
if(_curName != name) {
_curName = name;
Start(_iter->second, IsForward());
} else {
Advance(_iter->second, IsForward(), IsLooping());
}