4

概述:

我正在尝试改进我使用状态模式的程序的设计。我将发布问题的简要描述,当前设计的类图/描述的图像,然后是相关类的标头代码。

问题:

我正在为程序使用状态模式的变体。在这个变体中,我有一个“控制器”,它利用了两个抽象类,“状态”和“事件”,这两个抽象类都扩展了几个具体类型。这两个抽象类用于对因事件类型和当前状态而异的“事件”进行响应。每个状态都有一个“处理程序”函数,该函数被重载以获取每个具体事件类型。

“控制器”包含一个“事件”类型(抽象类)的队列,其中包含已发生的“事件”(具体类)列表。控制器一次“处理”每个事件,方法是从队列中检索它,并将其传递给该特定类型事件的状态处理程序。

问题是为了获得正确的类型以将事件传递给状态的适当处理程序,我必须将事件向下转换为正确的具体类型。目前,我通过向“状态”类 (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 );
}
4

2 回答 2

4

添加一个抽象方法:

virtual state *transition(state *from) = 0;

到事件。

然后在每个状态子类中实现如下:

state *transition(state *from)
{
    from->handle(this);
}

然后在你的循环中简单地调用:

nextState = nextEvent->transition(currentState);

编辑:

如果您将事件作为在其子类上模板化的模板类,您可以在事件类本身中实现转换:

template <class subclass> class event
{
    state *transition(state *from)
    {
        from->handle(dynamic_cast<subclass *>(this));
    }
}
于 2009-10-15T13:59:39.177 回答
0

Double Dispatch没有帮助吗?

于 2009-10-15T13:52:57.253 回答