c++中查找兄弟节点的状态

c++ finding the state of a sibling

本文关键字:状态 节点 兄弟 查找 c++      更新时间:2023-10-16

在我的代码中,有一个基类a,它有三个子类A1, A2, A3。这些对象有一个状态来指定它们是否处于活动状态。

现在在另一个类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()的东西,但兄弟姐妹之间的依赖关系使其变得困难。还有其他好的重构方法吗?类结构必须保持不变。

你可以重构它:

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

您可以使用以下函数来增强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中(根据告知不询问原则)会更好,但是对于驻留在b中的GetAObj,这可能会很棘手。