在我的代码中,有一个基类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(),但兄弟之间的依赖关系使其变得艰难。重构还有其他好的想法吗?类结构必须保持不变。
答案 0 :(得分: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的基本版本设为pure virtual,以强制用户实现特定于州的版本。
但是,您不应在子类中实现基于不同对象状态的任何内容。 IMO你应该在这种情况下使用管理器类型对象。如果真的想这样做,你应该只将对其他对象的引用传递给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; }
}
答案 1 :(得分: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上时,这可能会很棘手。