使用C ++解决State Pattern中的循环依赖

时间:2011-03-04 20:16:57

标签: c++ design-patterns

我正在尝试在C ++中实现状态模式,但是在循环依赖性方面存在问题。我在这里阅读了其他相关资料 - 遗憾的是它并没有帮助我。我对C ++没有很多经验,所以请耐心等待。 以下代码是在Eclipse Helios CDT中的Ubuntu 10.10机器上开发的:

ConcreteSystem.h

#ifndef CONCRETESYSTEM_H_
#define CONCRETESYSTEM_H_

class SystemState;

class ConcreteSystem {
public:
    ConcreteSystem();
    void SelfTestFailed();
    void Restart();
private:
    friend class SystemState;
    SystemState *currentState;
    void ChangeState(SystemState *state);
};

#endif /* CONCRETESYSTEM_H_ */

ConcreteSystem.cpp

#include "ConcreteSystem.h"
#include "SystemState.h"

ConcreteSystem::ConcreteSystem() {
    currentState = SelfTest::GetInstance();
}

void ConcreteSystem::SelfTestFailed() {
    currentState->SelfTestFailed(this);
}

void ConcreteSystem::Restart() {
    currentState->Restart(this);
}

void ConcreteSystem::ChangeState(SystemState *state){
    currentState = state;
}

SystemState.h

#ifndef SYSTEMSTATE_H_
#define SYSTEMSTATE_H_

class ConcreteSystem;

class SystemState {
public:
    virtual void Restart(ConcreteSystem *cs);
    virtual void SelfTestFailed(ConcreteSystem *cs);
protected:
    virtual void ChangeState(ConcreteSystem *cs, SystemState *state);
};

#endif /* SYSTEMSTATE_H_ */

SystemState.cpp

#include "SystemState.h"
#include "ConcreteSystem.h"

void SystemState::Restart(ConcreteSystem *cs) {

}

void SystemState::SelfTestFailed(ConcreteSystem *cs) {

}


void SystemState::ChangeState(ConcreteSystem *cs, SystemState *state) {
    cs->ChangeState(state);
}

SelfTest.h

#ifndef SELFTEST_H_
#define SELFTEST_H_

#include "SystemState.h"


class SelfTest : public SystemState {
public:
    SelfTest();
    void SelfTestFailed(ConcreteSystem* cs);
    static SystemState* GetInstance();
private:
    static SystemState* instance;
};

#endif /* SELFTEST_H_ */

SelfTest.cpp

#include "SelfTest.h"
#include "Failure.h"

SystemState* SelfTest::instance = 0;

SelfTest::SelfTest() {

}

void SelfTest::SelfTestFailed(ConcreteSystem *cs) {
    ChangeState(cs, Failure::GetInstance());
}

SystemState* SelfTest::GetInstance() {
    if (instance == 0) {
        instance = new SelfTest();
    }
    return instance;
}

Failure.h

#ifndef FAILURE_H_
#define FAILURE_H_

#include "SystemState.h"

class SelfTest;

class Failure : public SystemState {
public:
    Failure();
    void Restart(ConcreteSystem* t);
    static SystemState* GetInstance();
private:
    static SystemState* instance;
};

#endif /* FAILURE_H_ */

Failure.cpp

#include "Failure.h"
#include "SelfTest.h"

SystemState* Failure::instance = 0;

Failure::Failure() {

}

void Failure::Restart(ConcreteSystem* t) {
    ChangeState(t, SelfTest::GetInstance());
}

SystemState* Failure::GetInstance() {
    if (instance == 0) {
        instance = new Failure();
    }
    return instance;
}

我遇到了包含问题,这给了我一些奇怪的编译器错误。谁能很好地解决这个问题?

1 个答案:

答案 0 :(得分:3)

根据您发布的代码的外观,您将重新定义类。查看您的Failure.cpp文件,您有:

#include "Failure.h"
#include "SelfTest.h"

其中包含这两个文件,每个文件都包含SystemState.h文件。由于SystemState.h文件包含多次,因此它会尝试重新定义SystemState类。在每个头文件的顶部,您应该执行以下操作:

// SystemState.h
#ifndef SystemState_h
#define SystemState_h
.. class definition ..
#endif // close the if statement from above.

作为设计的一部分,我认为状态彼此了解是不好的形式 - 使用ConcreteSystem作为状态控制器,然后将状态基于最后一个状态操作的返回值。

另外,如果您对C ++缺乏经验,我建议looking at this作为学习资料的重要来源(当然还有StackOverflow!)。