home
/*
*
* Maquina de estados , utilizando el patron state y templates
* Author : Jon Ander Ortiz
* License: GPLV3 : ^_^
*
*/
#include <iostream>
using namespace std;
/*Clase State con acceso a la clase de la que forma el estado*/
template <class C> class State{
protected:
C* owner;
public:
State(C* o_):owner(o_){};
virtual ~State (){}
virtual void enter (){}
virtual void execute (){}
virtual void exit (){}
};
/* Clase que implementa los métodos de gestión de estados */
template <class T> class StateMachine {
private:
State<T> * current;
State<T> * last;
State<T> * context; //Este viene siendo un tanto opcional
public:
void setCurrentState(State<T>*);
State<T>* getCurrentState();
void update(); //Updatea la FSM (Finite state machine)
void changeState (State<T>* );
void returnLastState ();
};
template <class T> void StateMachine<T>::setCurrentState(State<T> * current_)
{this->current = current_;}
template <class T> State<T>* StateMachine<T>::getCurrentState()
{return this->current;}
template <class T> void StateMachine<T>::update()
{this->current->execute();}
template <class T> void StateMachine<T>::changeState(State<T>* t)
{
this->current->exit();
delete this->last;
this->last = this->current;
this->current = t;
this->current->enter();
}
template <class T> void StateMachine<T>::returnLastState()
{
this->current->exit();
this->last->enter();
}
//Diagrama de estados para el tema este:
// Estados de animo del objeto controlado (Cuando va hablando va cambiando de estado) :
// Estado 1 Estado 2 Estado 3
// Tiene pena ---------------->Esta Contento------------->Tiene Miedo
// /|\ |
// |_____________________________________________|
//
/*
Hay que definir primero las clases y luego los métodos todos seguidos, de esta manera podemos acceder de uno a otro sin problema, si lo ponemos de otra manera ya empieza a dar por saco
*/
class Controlado //Controlado tiene una bonita maquina de estados que regula su funcionamiento
{
private:
StateMachine<Controlado> sm;
public:
Controlado ();
StateMachine<Controlado> * getStateMachine();
void hablar();
};
/*Definición de los estados posibles, heredan de la plantilla state instanciada con el elemento
controlado, es decir, que son un estado del elemento controlado */
class ControladoConcreteStatePena : public State<Controlado>
{
private:
//Aqui rollos internos variados de X o de Y
public:
ControladoConcreteStatePena(Controlado * ctld);
void enter ();
void execute ();
void exit ();
};
class ControladoConcreteStateFeliz : public State<Controlado>
{
private:
//Aqui rollos internos variados de X o de Y
public:
ControladoConcreteStateFeliz(Controlado * ctld);
void enter ();
void execute ();
void exit ();
};
class ControladoConcreteStateMiedo: public State<Controlado>
{
private:
public:
ControladoConcreteStateMiedo(Controlado * ctld);
void enter ();
void execute ();
void exit ();
};
Controlado::Controlado()
{
sm.setCurrentState(new ControladoConcreteStatePena(this));
}
StateMachine<Controlado>* Controlado::getStateMachine()
{return &(this->sm);}
void Controlado::hablar()
{
sm.update(); //Ahora llama a el metodo execute de su estado actual
//En este punto hay dos maneras de funcionar que el mísmo execute
//cambie el estado de su Controlado, o que se controle desde la StateMachine
//Yo lo he echo desde el hijo, de echo es una de las razones de la
// arquitectura de la plantilla
}
ControladoConcreteStatePena::ControladoConcreteStatePena(Controlado * ctld): State<Controlado>(ctld)
{/*For other purpouses :P*/}
void ControladoConcreteStatePena::enter()
{
//Aqui tenemos acceso a lo que viene siendo el elemento controlado
cout<<"Entramos en el estado de pena"<<endl;
}
void ControladoConcreteStatePena::execute()
{
cout<<"Ejecutamos en el estado pena"<<endl;
cout<<"Ahi que penita que tengo!!!!"<<endl;
this->owner->getStateMachine()->changeState(new ControladoConcreteStateFeliz(this->owner));
}
void ControladoConcreteStatePena::exit()
{
cout<<"Ejecutamos salir del estado de pena"<<endl;
cout<<"Nos vamos animando"<<endl;
}
ControladoConcreteStateFeliz::ControladoConcreteStateFeliz(Controlado * ctld): State<Controlado>(ctld)
{}
void ControladoConcreteStateFeliz::enter()
{
cout<<"Entramos en el estado de felicidad"<<endl;
}
void ControladoConcreteStateFeliz::execute()
{
cout<<"Ahi que contento que estoy!!!!!"<<endl;
this->owner->getStateMachine()->changeState(new ControladoConcreteStateMiedo(this->owner));
}
void ControladoConcreteStateFeliz::exit()
{
cout<<"Ejecutamos salir del estado de felicidad"<<endl;
cout<<"Y nos vamos asustando"<<endl;
}
ControladoConcreteStateMiedo::ControladoConcreteStateMiedo(Controlado * ctld): State<Controlado>(ctld)
{}
void ControladoConcreteStateMiedo::enter()
{
cout<<"Entramos en el estado del miedo"<<endl;
}
void ControladoConcreteStateMiedo::execute()
{
cout<<"Me cago del miedo!!!!!"<<endl;
this->owner->getStateMachine()->changeState(new ControladoConcreteStatePena(this->owner));
}
void ControladoConcreteStateMiedo::exit()
{
cout<<"Ejecutamos salir del estado de Miedo"<<endl;
cout<<"Y nos va entrando la penita"<<endl;
}
int main (int argc, char * argv [])
{
Controlado * a = new Controlado();
a->hablar();
a->hablar();
a->hablar();
return 0;
}