2011-05-05 56 views
0

在我的代碼中,有一個基類A有三個子類A1,A2,A3。這些對象有一個狀態來指定它們是否處於活動狀態。C++找到兄弟的狀態

現在在另一個類B中創建A1,A2和A3的對象。現在,在B的內部功能,

int B::SetState(A& aObj) 
{ 
    //if aObj is an instance of A1, do nothing and return. 
    //if aObj is an instance of A2, do something if A3 is active 
    //if aObj is an instance of A3, do something if A2 is active 

    //the code below i would like to change to something more maintainable 
    if (aObj.GetNumber() == 0) 
     return; 

    A& otherAObj = aObj.GetNumber()==1? GetAObj(2) : GetAObj(3); 

    if (otherAObj.IsActive()) 
    { 
    //do something with aObj 
    } 

} 

我想代碼更改爲類似aObj.DoSomething(),但兄弟之間的相關性使得它很難。任何其他好的想法重構?班級結構必須保持不變。

+0

當你說「如果aObj包含A1」,你的意思是「如果A是A1類的一個實例」?如果是的話,你可能想要搜索雙重派遣和訪問者模式。 – Rom1 2011-05-05 08:15:59

+0

a)如果性能不成問題,您可以使用RTTI。 b)如果你可以改變A,A1,A2,A3然後使用一個虛函數並在派生類中覆蓋它。然後,所有你需要的是做一個aObj.DoSomething() – 2011-05-05 08:51:32

+0

如果你在* call *網站基於對象類型做條件行爲,那麼你可能確實需要重構... – 2011-05-05 08:55:34

回答

0

您可以重構這個:

if (otherAObj.IsActive()) 
{ 
    //do something with aObj 
} 

出到DoSomething的()函數

public class A{ 
    virtual bool isActive(){ return false; } 
    virtual bool isPending(){ return false; } 
    virtual void doSomething() 
    { 
     if(true == isActive()) 
     { 
      ... 
      if(false == isPending()) 
      { ... } 
      ... 
     } 
    }; 
} 

public class A_State_Active : A 
{ 
    bool isActive(){ return true; } 
} 

public class A_State_Pending : A 
{ 
    bool isPending(){ return true; } 
    void doSomething() 
    { 
     throw new InvalidOperationException("Don't be messing"); 
    } 
} 

甚至會使DoSomething的純虛迫使用戶實現的狀態特定版本的基礎版本。

但是,你不應該在你的子類中實現任何基於不同對象狀態的東西。在這種情況下,你應該使用一個管理器類型的對象。如果真的想這樣做,只需將對其他對象的引用傳遞給doSomething()函數,並根據傳遞對象狀態的返回值修改運行時行爲(使用「isActive」/「isPending」API查詢) 。

其他選擇是取消繼承和青睞構圖。有A是一個類,其中包含一個A_State類的引用。然後,您將子類A_State

class A 
{ 
    //public functions 
    ... 
    const A_State* getState(){ return m_poMyState; } 
    void setState(const A_State const * aStateObj){ m_poMyState = aStateObj; } 
} 
0

你可以提高在子類中使用函數A接口一樣

virtual bool hasSibling() const = 0; 
virual int siblingNumber() const = 0; 

然後,給出適合實現了B碼可以這樣做:

if (!aObj.hasSibling()) return; 
A & otherObj = GetAObj(aObj.siblingNumber()); 
if (otherObj.isActive()) { ... } 

這將會是更好的,如果你可以把更多的邏輯推到A中(在告訴別人原則上),但是當GetAObj駐留在B時可能會非常棘手。