2012-07-04 56 views
0

許多重複的切換語句似乎需要進行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; 
     } 
    } 
+0

它看起來像函數指針可能在這裏幫助。 –

+0

這是[代碼評論](http://codereview.stackexchange.com/)的好問題嗎? – jrok

+0

@jrok我在謹慎的一面犯錯。如果需要移動,請繼續。 – Casey

回答

1

其他的東西都應該摺疊成一個開關,以使相關的步驟更接近;例如

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

......都在這一個案例中。重複一些函數調用並不是什麼大問題,因爲它會使整個操作順序更加清晰。

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()); 
    } 
+0

第二個參數是一個框條。把它們想象成一片電影。他們自己沒有前進或後退的概念,只是他們的第一個,最後一個和每個框架。這是電影放映機以特定的方向運行電影。 – Casey

+0

@Casey:您可以應用相同的想法,並在控制類中使用方法(以strip作爲參數)。您也可以將它們作爲免費功能。 DRYing是關於將邏輯抽象爲函數的。請參閱編輯。 – molbdnilo