我想提高我使用状态模式的程序设计。我将发布一个关于这个问题的简要描述,一个当前设计的类图/描述的图像,以及相关类的标题代码。
问题:
我使用某个程序的状态模式的变化。在这个变体中,我有一个'控制器',它使用了两个抽象类'状态'和'事件',这两个抽象类扩展了几种具体类型。这两个抽象类用于对根据事件类型和当前状态而变化的“事件”进行响应。每个状态都有一个“处理程序”函数,它被重载以获取每个具体的事件类型。
'控制器'包含一个类型为'event'(抽象类)的队列,其中包含已发生的'events'(具体类)列表。控制器每次处理一个事件,通过从队列中检索每个事件,并将其传递给状态处理程序以处理特定类型的事件。
问题是,为了获得正确的类型以将事件传递给状态的相应处理程序,我必须将downcast事件转换为正确的具体类型。目前,我通过向每个具体事件类型实现的类'state'(getType())添加一个方法来完成此任务,并返回一个表示该事件类型的整数。然而,这种做法非常“不雅”,并导致使用枚举来驱动“切换”块和“向下转换” - 这不是很好的设计实践。
我该如何改变这种设计,让事件传递到更优雅的状态?
类图
标题代码
/*****
* CONTROLLER (driver) CLASS
*/
queue<event> events; //gets populated by other threads that hold reference to it
state* currentState;
vector<state*> allStates;
allStates.push_back(new state_1(&allStates)); // passes reference to 'allStates' to each state
allStates.push_back(new state_2(&allStates)); // so that it may return the 'next state'
...
while(true){
event nextEvent;
state* nextState;
if(events.size() > 0){
nextEvent = events.front(); //Get next Event
events.pop(); //remove from queue
switch(nextEvent.getType()){ //determine 'concrete type' based on 'getType method'
case 1:
//Downcast to concrete state type, and let state handle event
nextState = currentState->handle(*dynamic_cast<event_type_1*>(&nextEvent));
break;
case 2:
state* nextState = currentState->handle(*dynamic_cast<event_type_1*>(&nextEvent));
break;
...
}
//Transition to next state
currentState = nextState;
else
Sleep(5); //
}
/*****
* EVENT CLASSES
*/
class event{
public:
virtual int getType();
}
class event_type_1 : public event{
public:
int getType(){ return 1; };
int specializedFunc1();
double specializedFunc2();
}
class event_type_2 : public event{
public:
int getType(){ return 2; };
std::string specializedFunc3();
}
/*****
* STATE CLASSES
*/
class state{
protected:
vector<state*>* m_states;
public:
state(vector<state*>* p_states){ m_states = p_states; };
virtual state* handle(event_type_1);
virtual state* handle(event_type_2);
}
class state_1 : public state{
public:
state* handle(event_type_1);
state* handle(event_type_2);
}
class state_2 : public state{
public:
state* handle(event_type_1);
state* handle(event_type_2);
}
嘿, 我目前正在尝试您的建议... 如果我向类'事件'添加'transition(state * from)',这不会导致'循环依赖',其中类'event'和'state'是相互引用的吗? – simplyletgo 2009-10-15 14:16:55
是的,他们都会互相引用,但没关系。您需要在课前事件前转发声明课程状态,即 课程状态; //前置声明 class event {...} – atomice 2009-10-15 14:46:13
aha,我明白了!我甚至没有意识到你可以用C++中的类来做到这一点,这很酷。如果编译器在'event.h'和'state.h'中看到'class state'的定义,并且说'hell no',我会认为这会导致某种'重新定义问题'。 – simplyletgo 2009-10-15 15:03:38