我应该使用哪个?
struct IFilterTreeNode
{
virtual unsigned int GetEasiestProveRank() const = 0;
virtual unsigned int GetEasiestDisproveRank() const = 0;
virtual unsigned int GetEasiestProveNumber() const = 0;
virtual unsigned int GetEasiestDisproveNumber() const = 0;
virtual std::vector<IFilterTreeNode *> GetChildren() const = 0;
virtual bool AttemptToProve() = 0;
virtual bool AttemptToDisprove() = 0;
virtual ~IFilterTreeNode() {};
};
或:
class IFilterTreeNode
{
virtual unsigned int GetEasiestProveRankImpl() const = 0;
virtual unsigned int GetEasiestDisproveRankImpl() const = 0;
virtual unsigned int GetEasiestProveNumberImpl() const = 0;
virtual unsigned int GetEasiestDisproveNumberImpl() const = 0;
virtual std::vector<IFilterTreeNode *> GetChildrenImpl() const = 0;
virtual bool AttemptToProveImpl() = 0;
virtual bool AttemptToDisproveImpl() = 0;
public:
unsigned int GetEasiestProveRank() const
{
return GetEasiestProveRankImpl();
}
unsigned int GetEasiestDisproveRank() const
{
return GetEasiestDisproveRankImpl();
}
unsigned int GetEasiestProveNumber() const
{
return GetEasiestProveNumberImpl();
}
unsigned int GetEasiestDisproveNumber() const
{
return GetEasiestDisproveNumberImpl();
}
std::vector<IFilterTreeNode *> GetChildren() const
{
return GetChildrenImpl();
}
bool AttemptToProve()
{
return AttemptToProveImpl();
}
bool AttemptToDisprove()
{
return AttemptToDisproveImpl();
}
virtual ~IFilterTreeNode() {};
};
答案 0 :(得分:2)
我很懒,我们的大部分代码库都使用了第一个选择,所以这就是我要使用的那个。事情开始变得越来越复杂时,我会立即切换到第二个选择。但就像我说的那样,我很懒。 : - )
第二种选择肯定更具前瞻性和灵活性。优秀的程序员使课程易于使用。让它们易于编写是次要的。
答案 1 :(得分:2)
但我想补充一点:你的界面将适用于从中继承的所有类型。
所以,除非你能证明只关注少数几个类并且你将在你的控制范围内(并且那里没有脆弱的基类问题的风险),那么< b>你应该谨慎,并使用NVI模式。
因为一旦其他人开始从您的界面继承,就不会轻易回头。
答案 2 :(得分:1)
NVI习语的目标是分离界面和实现。根据面向对象的设计实践,这是你想要的。
如果你认为在这种情况下没有真正的理由这样做,我会做前者。 Herb Sutter argues quite the opposite
你也可能会问,“简单有多简单?”简单可以经常变得复杂。也许从前者开始,在你需要后者之前不要把它改为后者。
答案 3 :(得分:0)
在这个简单的案例中,可能不值得这么麻烦。如果方法有任何参数和/或需要可扩展的日志/仪表/参数预/后处理,我会使用NVI。