概述:
我正在尝试改进我使用状态模式的程序的设计。我将发布问题的简要描述,当前设计的类图/描述的图像,然后是相关类的标头代码。
问题:
我正在为程序使用状态模式的变体。在这个变体中,我有一个“控制器”,它利用了两个抽象类,“状态”和“事件”,这两个抽象类都扩展了几个具体类型。这两个抽象类用于对因事件类型和当前状态而异的“事件”进行响应。每个状态都有一个“处理程序”函数,该函数被重载以获取每个具体事件类型。
“控制器”包含一个“事件”类型(抽象类)的队列,其中包含已发生的“事件”(具体类)列表。控制器一次“处理”每个事件,方法是从队列中检索它,并将其传递给该特定类型事件的状态处理程序。
问题是为了获得正确的类型以将事件传递给状态的适当处理程序,我必须将事件向下转换为正确的具体类型。目前,我通过向“状态”类 (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 );
}