Как правильно сменить Состояние?
От: Wody  
Дата: 26.07.11 10:24
Оценка:
Добрый день. Теоретический вопрос про паттерн Состояние.
Имеем контекст, абстрактный класс состояния и два конкретных состояния (A, B). Как правильно в объекте A сменить состояние контекста и запустить метод f конкретного состояния B?

class Context;

class State
{
public:
 virtaul ~State() {}
 virtual void f() = 0;
protected:
 Context* c_;
};

class A: public State
{
public:
 A(Context* c): c_(c) {}
void f()
{
 //Тут нужно создать состояние B и изменить c_->s_, вызвать B::f() и удалить состояние A
 c_->s_ = new B(c_);
 c_->s_->f();
 delete this; //неприятно выглядит
}
};

class Context
{
public:
 Context(): s_(new A(this)) {}
 void f() { s_->f(); }
private:
 State* s_;
};


Как можно это лучше реализовать?
Re: Как правильно сменить Состояние?
От: BitField Украина http://lazy-bitfield.blogspot.com
Дата: 26.07.11 10:47
Оценка: 3 (1)
А если так?

class State {
public:
  virtual ~State() {}
  virtual State * change() = 0;
};

class StateA: public State {
  State * change();
};

class StateB: public State {
  State * change() {
    return new StateA();
  }
};

State * StateA::change() {
  return new StateB();
}

class Context {
public:
  Context(): 
    m_state(new StateA())
  {}
  
  void switch_state() {
    m_state.reset( m_state->change() );
  }
private:
  std::auto_ptr<State> m_state;
}
Re[2]: Как правильно сменить Состояние?
От: Wody  
Дата: 26.07.11 11:02
Оценка:
Здравствуйте, BitField, Вы писали:

Понял идею, спасибо. Действительно, в первую очередь надо взять auto_ptr
Но предполагается, что A сам решит в какое состояние перейти контексту и переведет контекст в это состояние (то есть в B, C, D и т.д.).

Забыл отметить, что в состояния имеют friend доступ к данным контекста

class Context
{
//...
friend class State;
};
Re: Как правильно сменить Состояние?
От: Centaur Россия  
Дата: 26.07.11 12:59
Оценка: 2 (1)
Здравствуйте, Wody, Вы писали:

W>Добрый день. Теоретический вопрос про паттерн Состояние.

W>Имеем контекст, абстрактный класс состояния и два конкретных состояния (A, B). Как правильно в объекте A сменить состояние контекста и запустить метод f конкретного состояния B?

Если A и B сами не имеют собственного состояния (в смысле, членов-данных), то рассмотри вариант, когда они не создаются и не удаляются, а существуют в виде глобальных констант или синглтонов. При необходимости перевести Контекст в новое Состояние, старое Состояние возвращает откуда-нибудь или передаёт куда-нибудь ссылку на новое Состояние.
Re: Как правильно сменить Состояние?
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 26.07.11 13:47
Оценка: 2 (1)
Здравствуйте, Wody, Вы писали:

W>Добрый день. Теоретический вопрос про паттерн Состояние.

W>Имеем контекст, абстрактный класс состояния и два конкретных состояния (A, B). Как правильно в объекте A сменить состояние контекста и запустить метод f конкретного состояния B?

W>Как можно это лучше реализовать?

Если состояния это код без данных, то можно использовать placement new т.е вместо delete this написать

(new (this) B)->f();


Выделенное важно.
Sic luceat lux!
Re[2]: Как правильно сменить Состояние?
От: zaufi Земля  
Дата: 28.07.11 17:59
Оценка: 3 (1)
Здравствуйте, Kernan, Вы писали:

K>Здравствуйте, Wody, Вы писали:


W>>Добрый день. Теоретический вопрос про паттерн Состояние.

W>>Имеем контекст, абстрактный класс состояния и два конкретных состояния (A, B). Как правильно в объекте A сменить состояние контекста и запустить метод f конкретного состояния B?

W>>Как можно это лучше реализовать?

K>Если состояния это код без данных,

а также без виртуальных функций, или при наследовании состояния не использовалось виртуальное наследовании, или не было множественного наследования состояния и компилятор без empty base optimization...

тогда да...

K> то можно использовать placement new т.е вместо delete this написать

K>
K>(new (this) B)->f(); 
K>


K>Выделенное важно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.