用C++设计和实现接口:如果我这样做,我就该死,如果我不这样做,我就该死



我需要一些关于c++中接口的继承和编码的帮助。我正在创建一个状态机,我将从中派生出另一个状态机。因此我有两个相互作用的部分,一个StateMachine和一个State。问题是,使用这种设计,我不能从StateMachineDerivedStateMachine中派生出专门的State

class StateMachine; //fwd
class State {
public:
virtual void action(StateMachine *engine) = 0;
virtual ~State() = default;
};
class StateMachine {
public:
StateMachine() = default;
explicit StateMachine(State &state) : state_(&state) {};
virtual void setState(State &state) {
state_ = &state;
}
[[nodiscard]] virtual State *getState() const {
return state_;
}
protected:
State *state_ = nullptr;
};
class DerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
return special_thing_;
}
void setSpecialState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};

DerivedStateDependsOnGeneralStateMachine的问题是StateMachine*不能访问doSpecializedThings()方法。

class DerivedStateDependsOnGeneralStateMachine : public State {
virtual void action(StateMachine *engine) {
int important_value = engine->doSpecializedThings();
};
};

DerivedStateDependsOnDerivedStateMachine的问题是,你不能用不同的参数重写父方法。

class DerivedStateDependsOnDerivedStateMachine : public State {
void action(DerivedStateMachine *engine) override {
engine->doSpecializedThings();
};
};

有谁能找到办法摆脱我给自己打的这个结吗?很明显我把设计搞砸了。在这种情况下,什么是"正常"(找不到更好的词了)?

编辑为了解决这些评论,首先@Ted Lyngmo我正在使用我在这篇文章中发现的状态机设计。奇怪的是,相互依赖是设计的一部分,但却是刻意为之。StateMachine需要始终保持对状态的引用,并且状态负责确定下一个状态。下一个状态可能取决于存储在StateMachine中的变量,所以在State中有对StateMachine的引用是很有用的。

更具体一点,我正在写一个扑克游戏。这个想法是有一个抽象的StateMachine接口,我可以从中派生出一个符合接口的PokerEngine状态机。我还认为我应该有一个抽象的State,从中我可以推导出PokerState。这些都可以在没有抽象层的情况下工作,并且最初可能更容易考虑,但对我来说,练习对接口进行编码以启用依赖注入和mock是很重要的。讽刺的是,在做这些事情的过程中,我违背了利斯科夫替换原理。无论如何,PokerEngine将需要做getPotAmount这样的事情,这是一个专门的方法,我不想任何StateMachine

我不完全理解你的设计,但是你可以这样做:

class StateMachine; //fwd
class State {
public:
virtual void action(StateMachine *engine) = 0;
virtual ~State() = default;
};
class StateMachine {
public:
StateMachine() = default;
explicit StateMachine(State &state) : state_(&state) {};
virtual void setState(State &state) {
state_ = &state;
}
virtual void setState(int state) {};
[[nodiscard]] virtual State *getState() const {
return state_;
}
virtual int doSpecializedThings(){
std::cout << "Do StateMachine things (or nothing)" << std::endl;
return 0;
}

protected:
State *state_ = nullptr;
};
class DerivedStateDependsOnGeneralStateMachine : public State {
public:
virtual void action(StateMachine *engine) {
int important_value = engine->doSpecializedThings();
};
};
class DerivedStateDependsOnDerivedStateMachine : public State {
public:
void action(StateMachine *engine) override {
engine->doSpecializedThings();
};
};
class DerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
std::cout << "Do DerivedStateMachine things " << std::endl;
return special_thing_;
}
void setState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};
class AnotherDerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
std::cout << "Do AnotherDerivedStateMachine things and" << std::endl;
std::cout << "tcalling base class: ";
StateMachine::doSpecializedThings();
return special_thing_;
}
void setState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};
int main()
{
StateMachine sm;
DerivedStateMachine dsm;
AnotherDerivedStateMachine adsm;
DerivedStateDependsOnGeneralStateMachine dsmg;
DerivedStateDependsOnDerivedStateMachine dsmd;

sm.setState (dsmg);
StateMachine * pdsm = &dsm;
pdsm->setState (dsmd);
dsm.setState (1);
dsmg.action (&dsm);
dsmd.action (&dsm);
dsmg.action (&sm);
dsmd.action (&sm);
dsmd.action (&adsm);

return 0;
}

我不明白为什么你在StateMachine中需要State,因为你从State调用StateMachine

最后,通过将抽象类型转换为派生类型,我能够访问所需的变量和方法

相关内容

最新更新