2011-05-05 73 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时可能会非常棘手。