重复切换语句需要重构

时间:2012-07-04 21:10:14

标签: c++ refactoring switch-statement

许多重复的切换语句似乎需要干掉。有什么建议? (包括无所事事!)

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;
        }
    }

2 个答案:

答案 0 :(得分:1)

将逻辑推入_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());
    }

答案 1 :(得分:1)

其他内容下的所有东西都应该折叠成一个开关,以使相关步骤更加接近; e.g。

case DIR_FORWARD_LOOPING:
    _iter->second->Next();
    if (_iter->second->IsAtEnd()) {
        _iter->second->First();
    }
    break;

......在那一个案例中都是如此。当它使整个动作序列更加清晰时,重复几个函数调用并不是什么大问题。