重复的开关语句需要重构



许多重复的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());
    }

最新更新